2015-06-07 18 views
7

Tác phẩm này và vui vẻ in 81:Tại sao `class X: mypow = pow` hoạt động? Còn về `self` thì sao?

class X: 
    mypow = pow 

print(X().mypow(3, 4)) 

Nhưng tại sao? Không phải là phương pháp đưa ra đối số "tự" bổ sung và nên hoàn toàn bối rối?

Để so sánh, tôi cũng đã thử nó với riêng Pow chức năng của tôi:

def Pow(x, y, z=None): 
    return x ** y 

class Y: 
    myPow = Pow 

print(Pow(3, 4)) 
print(Y().myPow(3, 4)) 

Chức năng trực tiếp gọi in 81 và các vụ đụng gọi phương thức như mong đợi, vì nó không có được điều đó thêm lập luận Ví dụ:

Python 3: TypeError: unsupported operand type(s) for ** or pow(): 'Y' and 'int' 
Python 2: TypeError: unsupported operand type(s) for ** or pow(): 'instance' and 'int' 

Tại sao/Pythons sở hữu pow hoạt động ở đây như thế nào? The documentation không giúp đỡ và tôi không thể tìm thấy nguồn.

+0

Tương tự như vậy nó được truyền cho 'Pow' của tôi? @PadraicCunningham –

+1

Đó là vì thuộc tính '__self__' của hàm dựng sẵn không thể ghi được, do đó nó luôn là' None' cho 'pow'. –

+0

@vaultah Hãy thử bằng Python 2. –

Trả lời

5

Điều này là do hàm python được xác định trong C (nội trang) có đối số tự xử lý tự động. Đây là tiêu đề hàm pow:

static PyObject * math_pow(PyObject *self, PyObject *args) Tại đây bạn có thể thấy rằng bản thân luôn được thông dịch bởi người phiên dịch.

+0

Đó không phải là' math.pow', không phải là 'pow'? –

+0

Đó là math.pow, nhưng hành vi là như nhau. –

+0

Hmm, tôi đã kiểm tra và xác nhận nó hoạt động giống nhau trong vấn đề đó (tức là, vui vẻ trả về 81.0). Tôi tìm thấy [nguồn đó] (https://github.com/python-git/python/blob/master/Modules/mathmodule.c#L927) và nó chỉ bỏ qua đối số 'self'. Tôi đoán tôi cần biết phương thức do người dùng định nghĩa * không * bỏ qua nó để thực sự hiểu nó. AshwiniChaudhary cũng bình luận gì đó về '__self__' của buildin không thể ghi, mà tôi đã xác nhận, nhưng tôi đoán điều đó không quan trọng nếu nó không được sử dụng.Tôi sẽ xem xét một chút về cả hai vấn đề. –

2

Hành vi này được kết nối với method binding. Có một cái nhìn vào những gì Python nói với bạn về các chức năng/phương pháp:

>> pow 
<built-in function pow> 
>>> X.mypow 
<built-in function pow> 
>>> X().mypow 
<built-in function pow> 

>>> Pow 
<function Pow at 0x7f88f5715f50> 
>>> Y.myPow 
<unbound method Y.Pow> 
>>> Y().myPow 
<bound method Y.Pow of <__main__.Y instance at 0x7f88f57117e8>> 

Tiếp tục các trạng thái tài liệu:

Lớp điển lưu trữ các phương pháp như các chức năng. Trong định nghĩa lớp, các phương thức được viết bằng cách sử dụng deflambda, các công cụ thông thường để tạo các hàm. [...]

Để hỗ trợ các cuộc gọi phương thức, các hàm bao gồm phương thức __get__() cho các phương thức liên kết trong khi truy cập thuộc tính. Điều này có nghĩa là tất cả các hàm đều là các bộ mô tả phi dữ liệu trả về các phương thức bị ràng buộc hoặc không liên kết phụ thuộc vào việc chúng được gọi từ một đối tượng hay một lớp. [...]

Nhưng chức năng tích hợp sẵn không có phương thức __get__(). Đó là lý do tại sao pow không bị ràng buộc và có thể được sử dụng theo cách bạn quan sát, trong khi Pow không thể.

Các vấn đề liên quan