Đây là một câu hỏi rất thú vị!
Trong điều kiện của bạn, chúng xuất hiện giống nhau:
Python 2.7.2 (default, Oct 11 2012, 20:14:37)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class Foo(object):
... def method(self): pass
...
>>> a, b = Foo(), Foo()
>>> a.method == b.method
False
>>> id(a.method), id(b.method)
(4547151904, 4547151904)
Tuy nhiên, hãy chú ý rằng khi bạn làm bất cứ điều gì với họ, họ trở nên khác nhau:
>>> a_m = a.method
>>> b_m = b.method
>>> id(a_m), id(b_m)
(4547151*9*04, 4547151*5*04)
Và sau đó, khi kiểm tra một lần nữa, họ đã thay đổi một lần nữa!
>>> id(b.method)
4547304416
>>> id(a.method)
4547304416
Khi một phương pháp trên một cá thể được truy cập, một thể hiện của "phương pháp ràng buộc" được trả về. Một phương pháp ràng buộc lưu trữ một tham chiếu đến cả hai trường hợp và đối tượng chức năng của phương pháp:
>>> a_m
<bound method Foo.method of <__main__.Foo object at 0x10f0e9a90>>
>>> a_m.im_func is Foo.__dict__['method']
True
>>> a_m.im_self is a
True
(lưu ý rằng tôi cần phải sử dụng Foo.__dict__['method']
, không Foo.method
, vì Foo.method
sẽ mang lại một "phương pháp cởi ra" ... mục đích mà là một bài tập cho người đọc)
Mục đích của đối tượng "phương pháp liên kết" này là làm cho các phương thức "hoạt động hợp lý" khi chúng được truyền xung quanh như các hàm. Ví dụ: khi tôi gọi hàm a_m()
, tức là giống hệt để gọi a.method()
, mặc dù chúng tôi không có tham chiếu rõ ràng đến a
nữa. Ngược lại hành vi này với JavaScript (ví dụ), trong đó var method = foo.method; method()
không không sản xuất cùng một kết quả như foo.method()
.
SO! Điều này đưa chúng ta trở lại câu hỏi ban đầu: tại sao dường như id(a.method)
mang lại giá trị giống như id(b.method)
? Tôi tin rằng Asad là chính xác: nó phải làm với bộ gom rác đếm tham chiếu của Python *: khi biểu thức id(a.method)
được đánh giá, một phương thức ràng buộc được cấp phát, ID được tính toán, và phương thức ràng buộc được deallocated. Khi phương pháp ràng buộc tiếp theo - cho b.method
- được cấp phát, nó được cấp phát chính xác cùng một vị trí trong bộ nhớ, vì không có bất kỳ phân bổ nào (hoặc đã là số lượng cân bằng) do phương pháp ràng buộc cho a.method
được phân bổ. Điều này có nghĩa là a.method
dường như có cùng một vị trí bộ nhớ là b.method
. Cuối cùng, điều này giải thích tại sao các vị trí bộ nhớ dường như thay đổi lần thứ hai chúng được kiểm tra: các phân bổ khác đã diễn ra giữa lần kiểm tra thứ nhất và thứ hai có nghĩa là lần thứ hai chúng được phân bổ tại một vị trí khác (lưu ý: chúng được phân bổ lại bởi vì tất cả các tham chiếu đến chúng đều bị mất; các phương thức liên kết được lưu trữ †, do đó truy cập cùng một phương thức hai lần sẽ trả về cùng một cá thể: a_m0 = a.method; a_m1 = a.method; a_m0 is a_m1 => True
).
*: pedants lưu ý: thực ra, điều này không liên quan gì đến bộ thu rác thực tế, chỉ tồn tại để đối chiếu với tham chiếu vòng tròn… nhưng… đó là một câu chuyện cho một ngày khác.
†: ít nhất trong CPython 2.7; CPython 2.6 dường như không cache các phương thức bị ràng buộc, điều này sẽ khiến tôi mong đợi rằng hành vi không được chỉ định.
thể trùng lặp của http://stackoverflow.com/ Câu hỏi/13348031/python-bound-và-unbound-method-object –
@AnkitJaiswal nó khác nhau – jamylak