python - 为什么 `instance_of_object.foo is instance_of_object.foo` 评估为 False?

标签 python introspection

<分区>

如果我有一个

class A:
  def foo(self):
    pass

计算结果为 True:

getattr(A, 'foo') is A.foo

但这计算为False:

a = A()
getattr(a, 'foo') is a.foo

同样

a.foo is a.foo

为什么?

我发现 getattr(a, 'foo')a.foo 都是用

表示的
<bound method A.foo of <__main__.A object at 0x7a2c4de10d50>>)

所以那里没有提示....

最佳答案

至少在 CPython 中,绑定(bind)方法被实现为类 method 的实例。每次请求绑定(bind)函数的值时,都会得到此类的实例。

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

这个类所做的只是存储对实例和未绑定(bind)函数的引用,当您调用该类时,它会使用存储的实例(以及您的其他参数)调用未绑定(bind)函数。

未绑定(bind)函数,如 A.foo,只是常规的旧函数 - 没有构造代理类的新实例,因此身份如您所愿地工作。

造成这种差异的原因是 a.foo 的语义取决于两个事物,a 的值和A.foo。为了能够在以后的任何时间点得到这个含义,这两个值都需要被存储。这就是 method 类的作用。

相反,A.foo 的含义仅取决于一个值:A.foo。因此不需要额外的工作来存储任何东西,而是使用值本身。

您可能会考虑预分配绑定(bind)方法实例的想法,以便 a.foo 始终返回相同的不可变对象(immutable对象) - 但考虑到 Python 的动态特性,它更简单且成本更低每次都构建一个新的,即使它们可能是相同的。

关于python - 为什么 `instance_of_object.foo is instance_of_object.foo` 评估为 False?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50498770/

相关文章:

python - .format() 使用 {0 :g} to remove trailing zeros 时返回 ValueError

Python在拆分中跳过连续的分隔符

java - 在 Java 中获取变量的名称

python - 检查 `concurrent.futures.ThreadPoolExecutor`

python - 如何反省 win32com 包装器?

具有互斥可选参数的 python 类/子类,使用父类(super class)的实例作为可能的构造函数

python - get_or_create() 问题

python - 使用 pandas GroupBy.agg() 对同一列进行多个聚合

python - 从框架对象获取文档字符串

python - 出于测试目的访问原始装饰函数