Python 为什么实例对象和类对象之间的方法id不相同?
我想知道为什么Python 为什么实例对象和类对象之间的方法id不相同?,python,function,methods,Python,Function,Methods,我想知道为什么方法存在两个副本,一个是实例对象,另一个是类对象,为什么它是这样设计的 class Bar(): def方法(自我): 通过 @类方法 def cls方法(cls): 通过 b1=巴() b2=巴() 打印(条形方法,id(条形方法)) 打印(b1.方法,id(b1.方法)) 打印(b2.方法,id(b2.方法)) 打印(Bar.clsmethod,id(Bar.clsmethod)) 打印(b1.clsmethod,id(b1.clsmethod)) 打印(b2.clsmetho
方法存在两个副本,一个是实例对象,另一个是类对象,为什么它是这样设计的
class Bar():
def方法(自我):
通过
@类方法
def cls方法(cls):
通过
b1=巴()
b2=巴()
打印(条形方法,id(条形方法))
打印(b1.方法,id(b1.方法))
打印(b2.方法,id(b2.方法))
打印(Bar.clsmethod,id(Bar.clsmethod))
打印(b1.clsmethod,id(b1.clsmethod))
打印(b2.clsmethod,id(b2.clsmethod))
此设计是基于。通过定义\uuu get\uu
方法,每个函数恰好都是非数据描述符:
>>def foo():
... 通过
...
>>>foo.\u__
当代码中有表达式x.y
时,这意味着在对象x
上查找属性y
。具体规则是,其中一个规则涉及y
是存储在x
类(或任何子类)上的(非)数据描述符。以下是一个例子:
>>类Foo:
... def测试(自我):
... 通过
...
这里Foo.test
在类Foo
上查找名称test
。结果是在全局命名空间中定义的函数:
>>Foo.test
但是,正如我们上面所看到的,每个函数也是一个描述符,因此如果您在Foo
的实例上查找test
,它将调用描述符的\uu get\uuu
方法来计算结果:
>f=Foo()
>>>f.试验
我们可以通过手动调用Foo.test.\uuu get\uuu
获得类似的结果:
>>Foo.test.\uuuuu获取(f,类型(f))
这种机制确保实例(通常通过self
表示)作为第一个参数传递给实例方法。描述符返回绑定方法(绑定到执行查找的实例),而不是原始函数。此绑定方法在调用时将实例作为第一个参数插入。每次执行Foo.test
时,都会返回一个新的绑定方法对象,因此它们的id
s不同
classmethod
s的情况与调用的位置类似。唯一的区别是,对于实例object.\uuuuu getattribute.\uuuu
调用,而对于类type.\uuu getattribute.\uuu
则优先
类栏:
... @类方法
... def测试(cls):
... 通过
...
>>>条形试验
>>>Bar.\uuuuu dict\uuuuu['test']。\uuuuuu get\uuuuuu(无,Bar)
您是否希望b1.method()
、b2.method()
和Bar.method()
的行为相同…?但正如我所测试的,每次我执行Foo.test
时,它都会返回具有相同id的对象。f.test
我知道为什么print(id(f.test))
总是打印相同的值,因为每次A.test
的\uuuuuu get\uuuu
方法返回一个绑定方法对象,但没有人会接收或保留它,那么它就会被释放,在下一个语法中,绑定方法被分配到上一个位置,因此id是相同的。@Gordon实际上,内存空间被释放,然后重新使用。您需要比较f.test是f.test
,其计算结果为False
。