如果我有一个
class A:
def foo(self):
pass
这评估为True
:
getattr(A, 'foo') is A.foo
但这评估为False
:
a = A()
getattr(a, 'foo') is a.foo
as does
a.foo is a.foo
Why?
我找到getattr(a, 'foo')
and a.foo
两者都由
<bound method A.foo of <__main__.A object at 0x7a2c4de10d50>>)
所以没有任何提示......
至少在 CPython 中,绑定方法是作为类的实例实现的method
。每次你询问绑定函数的值时,你都会得到一个new这个类的实例。
x = a.foo
y = a.foo
assert x is not y
id(x) # E.g. 139664144271304
id(y) # E.g. 139664144033992
type(x) # <class 'method'>
type(y) # <class 'method'>
这个类所做的只是存储对实例的引用和unbound函数,当您调用该类时,它会使用存储的实例(以及其他参数)调用未绑定的函数。
未绑定的函数,例如A.foo
,只是常规的旧函数 - 没有构建代理类的新实例,因此身份按您的预期工作。
造成这种差异的原因是语义a.foo
依赖于取决于two事物、事物的价值a
和价值A.foo
。为了能够在以后的任何时间点获得这个含义,这两个值都需要存储。这就是method
类确实如此。
反之,其含义为A.foo
仅取决于一个值:A.foo
。因此不需要额外的工作来存储任何内容,并且使用值本身。
您可能会考虑预分配绑定方法实例的想法,以便a.foo
总是返回相同的不可变对象 - 但考虑到 Python 的动态特性,每次构造一个新对象会更简单、更便宜,即使它们可能是相同的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)