python - 为什么方法与自身不相同?

标签 python comparison identity

Python documentation about the is operator说:

The operators is and is not test for object identity: x is y is true if and only if x and y are the same object. x is not y yields the inverse truth value.

让我们试试看:

>>> def m():
...   pass
... 
>>> m is m
True

Python documentation also says :

Due to automatic garbage-collection, free lists, and the dynamic nature of descriptors, you may notice seemingly unusual behaviour in certain uses of the is operator, like those involving comparisons between instance methods, or constants. Check their documentation for more info.

>>> class C:
...   def m():
...     pass
... 
>>> C.m is C.m
False

我搜索了更多解释,但找不到任何解释。

为什么 C.m 是 C.m 错误?

我正在使用 Python 2.x。如以下答案中所述,在 Python 3.x 中,C.m is C.m 为真。

最佳答案

当您请求作为函数的实例的属性时,您会得到一个绑定(bind)方法:一个可调用对象,它包装类中定义的函数并将该实例作为第一个参数传递。在 Python 2.x 中,当您请求类的一个函数属性时,您会得到一个类似的代理对象,称为未绑定(bind)方法:

>>> class A: m = lambda: None
...
>>> A.m
<unbound method A.<lambda>>

这个特殊对象是在您请求时创建的,显然没有缓存在任何地方。这意味着当你这样做时

>>> A.m is A.m
False

您正在创建两个不同 未绑定(bind)方法对象并测试它们的身份。

注意

>>> x = A.m
>>> x is x
True

>>> A.m.im_func is A.m.im_func
True

工作正常。 (im_func 是未绑定(bind)方法对象包装的原始函数。)

顺便说一下,在 Python 3.x 中,C.m is C.m 是 True,因为(有点无意义的)未绑定(bind)方法代理对象被完全删除,您只得到您定义的原始函数。


这只是 Python 中属性查找的动态特性的一个示例:当您请求对象的属性时,可以运行任意 Python 来计算该属性的值。这是您的测试失败的另一个示例,其中更清楚原因:

>>> class ChangingAttribute(object):
...     @property
...     def n(self):
...             self._n += 1
...             return self._n
...
...     def __init__(self):
...             self._n = 0
...
>>> foo = ChangingAttribute()
>>> foo.n
1
>>> foo.n
2
>>> foo.n
3
>>> foo.n is foo.n
False
>>> foo.n
6

关于python - 为什么方法与自身不相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4639908/

相关文章:

python - python中许多正则表达式的速度

python - 桌面开发语言是编译二进制还是脚本语言(windows)?

java - 比较两个非常大的列表的最佳方法

asp.net - Entity Framework 代码优先 - 无效的列名 'Discriminator1'

代码签名中缺少 iPhone 发行版身份

python - python3.5中无法导入Kicad的Pcbnew

python - 如何修改 gzip 压缩的 tar 文件中的文件?

c++ - 比较函数中如何优化多个独立条件分支?

java - 如何比较 Java 中属性中也包含列表的两个对象

SQL身份(1,1)从0开始