gpt4 book ai didi

python - 为什么同一个类的不同对象的方法有相同的id?

转载 作者:太空狗 更新时间:2023-10-29 20:38:52 26 4
gpt4 key购买 nike

在下面的代码中,我不明白为什么useless_func属于两个不同的对象时,id是一样的?

class parent(object):
@classmethod
def a_class_method(cls):
print "in class method %s" % cls

@staticmethod
def a_static_method():
print "static method"

def useless_func(self):
pass

p1, p2 = parent(),parent()

id(p1) == id(p2) // False

id(p1.useless_func) == id(p2.useless_func) // True

最佳答案

这是一个非常有趣的问题!

在您的条件下,它们确实看起来是一样的:

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)

但是,请注意,一旦您对它们进行了任何操作,它们就会变得不同:

>>> a_m = a.method
>>> b_m = b.method
>>> id(a_m), id(b_m)
(4547151*9*04, 4547151*5*04)

然后,当再次测试时,它们又变了!

>>> id(b.method)
4547304416
>>> id(a.method)
4547304416

当访问实例上的方法时,返回“绑定(bind)方法”的实例。绑定(bind)方法存储对实例和方法的函数对象的引用:

>>> 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

(请注意,我需要使用 Foo.__dict__['method'],而不是 Foo.method,因为 Foo.method 将产生一个“未绑定(bind)方法”……其目的留给读者作为练习)

这个“绑定(bind)方法”对象的目的是使方法在像函数一样传递时“表现得明智”。例如,当我调用函数 a_m() 时,这与调用 a.method() 相同,即使我们没有不再是对 a 的显式引用。将此行为与 JavaScript 进行对比(例如),其中 var method = foo.method; method() 不会产生与 foo.method() 相同的结果。

所以!这让我们回到最初的问题:为什么 id(a.method) 产生的值与 id(b.method) 相同?我相信 Asad 是正确的:它与 Python 的引用计数垃圾收集器*有关:当表达式 id(a.method) 被评估时,绑定(bind)方法被分配,ID 被计算,并且绑定(bind)方法被释放。当下一个绑定(bind)方法——对于 b.method——被分配时,它被分配到内存中完全相同的位置,因为自那以后没有任何(或平衡数量的)分配a.method 的绑定(bind)方法已分配。这意味着 a.method 似乎与 b.method 具有相同的内存位置。

最后,这解释了为什么内存位置在第二次检查时似乎发生了变化:在第一次和第二次检查之间发生的其他分配意味着,第二次,它们被分配在不同的位置(注意:它们被重新分配,因为对它们的所有引用都丢失了;绑定(bind)方法被缓存†,因此两次访问相同的方法将返回相同的实例:a_m0 = a.method; a_m1 = a.method; a_m0 is a_m1 => 真).

*: Nerd 注意:实际上,这与实际的垃圾收集器无关,垃圾收集器的存在只是为了处理循环引用……但是……那是另一天的故事。
†:至少在 CPython 2.7 中; CPython 2.6 似乎没有缓存绑定(bind)方法,这让我认为没有指定行为。

关于python - 为什么同一个类的不同对象的方法有相同的id?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16727490/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com