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