Theo tài liệu cho các mô-đun Weakref:
Trong phần tiếp theo, các referent hạn có nghĩa là đối tượng mà được gọi bởi một tham chiếu yếu.
Tham chiếu yếu đến một đối tượng không phải là đủ để giữ các đối tượng còn sống: khi tài liệu tham khảo duy nhất còn lại để một vật ám chỉ là tài liệu tham khảo yếu, rác bộ sưu tập là miễn phí để tiêu diệt các referent và tái sử dụng bộ nhớ của nó đối với thứ gì khác.
Whats xảy ra với MyCallbackA là bạn đang nắm giữ một tham chiếu đến nó trong trường hợp của A, nhờ -
self.MyCallbackA = MyCallbackA
Bây giờ, không có tham chiếu đến phương pháp MyCallbackB ràng buộc trong mã của bạn. Nó chỉ được tổ chức trong một lớp học ___.__ dict__ như một phương pháp không liên kết. Về cơ bản, một phương thức ràng buộc được tạo ra (và trả về cho bạn) khi bạn làm self.methodName. (AFAIK, một phương thức ràng buộc hoạt động như một thuộc tính-sử dụng một bộ mô tả (chỉ đọc): ít nhất là đối với các lớp kiểu mới. Tôi chắc chắn, một cái gì đó tương tự như w/o descriptors sẽ xảy ra cho các lớp kiểu cũ. một người nào đó có kinh nghiệm hơn để xác minh yêu cầu về các lớp kiểu cũ.) Vì vậy, self.MyCallbackB chết ngay khi weakref được tạo ra, bởi vì không có tham chiếu mạnh mẽ đến nó!
kết luận của tôi là dựa trên: -
import weakref
#Trace is called when the object is deleted! - see weakref docs.
def trace(x):
print "Del MycallbackB"
class A(object):
def __init__(self):
def MyCallbackA():
print 'MyCallbackA'
self.MyCallbackA = MyCallbackA
self._testA = weakref.proxy(self.MyCallbackA)
print "Create MyCallbackB"
# To fix it, do -
# self.MyCallbackB = self.MyCallBackB
# The name on the LHS could be anything, even foo!
self._testB = weakref.proxy(self.MyCallbackB, trace)
print "Done playing with MyCallbackB"
def MyCallbackB(self):
print 'MyCallbackB'
def test_a(self):
self._testA()
def test_b(self):
self._testB()
if __name__ == '__main__':
a = A()
#print a.__class__.__dict__["MyCallbackB"]
a.test_a()
Output
Tạo MyCallbackB
Del MycallbackB
Xong chơi với MyCallbackB
MyCallbackA
Lưu ý:
Tôi đã thử xác minh điều này cho các lớp kiểu cũ. Hóa ra là "in a.test_a .__ get__" đầu ra -
<method-wrapper '__get__' of instancemethod object at 0xb7d7ffcc>
cho cả hai lớp phong cách mới và cũ. Vì vậy, nó có thể không thực sự là một descriptor, chỉ cần một cái gì đó mô tả giống như. Trong mọi trường hợp, điểm là một đối tượng phương thức liên kết được tạo ra khi bạn truy cập một phương thức cá thể thông qua bản thân, và trừ khi bạn duy trì một tham chiếu mạnh mẽ đối tượng đó, nó sẽ bị xóa.
Đối với python 3 thay thế 'item.im_func' với' mục .__ func__' và 'item.im_self' với 'mục .__ self__' – lou
Có thể cần' 'def __eq __ (tự, khác): trả khác() == self() ''? Đó có phải là mẫu so sánh tốt nhất không? (và có lẽ '' __ne__'' là nghịch đảo) – Rafe