[Python] Class 的 member function 每次取得位址不同
專案的程式最近遇到一個問題,
同事把一個 class 的 member function 加到 list 裡面作 callback 用,
為了預防重覆,因此會用類似 if func in list_func 的寫法來判斷,
但後來發現這招無效,每次 func 的位址都不一樣…
查了一下,原來 python 裡的 member function 是每次存取時,
都會產生一個新的物件,所以位址是不一樣的,
這跟 C++ 是蠻不同的概念~
參考資料:
stackoverflow: Why don’t methods have reference equality?
stackoverflow: Why does id() of an unbound method in Python 2 change for every access
做個實驗吧~先建立五個 A 物件:
>>> class A(object): ... def foo(self): ... print "foo" ... >>> a_list = [A() for i in xrange(5)] >>> pprint([a.foo for a in a_list]) [<bound method A.foo of <__main__.A object at 0x108dd7150>>, <bound method A.foo of <__main__.A object at 0x108dd7190>>, <bound method A.foo of <__main__.A object at 0x108dd71d0>>, <bound method A.foo of <__main__.A object at 0x108dd7210>>, <bound method A.foo of <__main__.A object at 0x108dd7250>>]
比較看看… 嗯,這五個 A 物件指到的 foo 全都不一樣:
>>> a_list[0].foo == a_list[1].foo False >>> a_list[0].foo == a_list[2].foo False
foo 是一個 instancemethod 物件:
>>> type(a_list[0].foo) <type 'instancemethod'> >>> dir(a_list[0].foo) ['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__func__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'im_class', 'im_func', 'im_self']
若是真的要比較它們指向的是不是同一個 member function 的話,
可以看一下 im_func 屬性,就會是一樣的了:
>>> pprint([a.foo.im_func for a in a_list]) [<function foo at 0x108dbfed8>, <function foo at 0x108dbfed8>, <function foo at 0x108dbfed8>, <function foo at 0x108dbfed8>, <function foo at 0x108dbfed8>] >>> a_list[0].foo.im_func == a_list[1].foo.im_func True
感想:python 真的跟 C/C++ 很不同呀…
(本頁面已被瀏覽過 435 次)