为什么`instance_of_object.foo被instance_of_object.foo`评估为False? [英] Why does `instance_of_object.foo is instance_of_object.foo` evaluate False?

查看:99
本文介绍了为什么`instance_of_object.foo被instance_of_object.foo`评估为False?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有

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中,绑定方法被实现为类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 函数的引用,当您调用该类时,它将与存储的实例(以及您的其他参数)一起调用unbound函数. /p>

A.foo一样,未绑定函数只是常规的旧函数-没有构造新的代理类实例,因此身份可以按您期望的方式工作.

产生这种差异的原因是a.foo的语义取决于两件事,即a的值和A.foo的值.为了能够在以后的任何时间点获得此含义,这两个值都需要存储.这是method类的作用.

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

您可能会考虑预分配绑定方法实例的想法,以便a.foo总是返回相同的不可变对象-但考虑到Python的动态特性,每次构造一个新对象都是更简单和便宜的,即使它们可以相同.

If I have a

class A:
  def foo(self):
    pass

this evaluates to True:

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

but this evaluates to False:

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

as does

a.foo is a.foo

Why?

I found that getattr(a, 'foo') and a.foo both are represented by

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

So no hint there....

解决方案

At least in CPython, bound methods are implemented as an instance of a class method. Every time you ask for the value of a bound function, you get a new instance of this class.

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

All this class does is store a reference to the instance and the unbound function, and when you call the class it calls the unbound function with the stored instance (along with your other arguments).

Unbound functions, like A.foo, are just regular old functions - no new instances of proxy classes are being constructed, so identity works as you expect.

The reason for this difference is that the semantic meaning of a.foo depends on two things, the value of a and the value of A.foo. In order to be able to get this meaning at any point in time later, both of these values need to be stored. This is what the method class does.

Conversely, the meaning of A.foo depends only on a single value: A.foo. So no additional work is required to store anything, and the value itself is used.

You might consider the idea of pre-allocating bound method instances, so that a.foo always returns the same immutable object - but given the dynamic nature of Python, it is simpler and cheaper to just construct a new one each time, even if they could be the same.

这篇关于为什么`instance_of_object.foo被instance_of_object.foo`评估为False?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆