运算符'非常奇怪'的行为方法

Cha*_*eon 47 python methods python-2.7 python-internals

为什么是第一个结果False,如果不是True

>>> from collections import OrderedDict
>>> OrderedDict.__repr__ is OrderedDict.__repr__
False
>>> dict.__repr__ is dict.__repr__
True
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 56

对于用户定义的函数,在Python 2中,通过描述符协议按需创建未绑定绑定的方法; 是一个这样的方法对象,因为包装函数是作为纯Python函数实现的.OrderedDict.__repr__

描述符协议将在支持它的对象上调用该__get__方法,因此__repr__.__get__()每当您尝试访问时都会调用该方法OrderedDict.__repr__ ; 对于类None(没有实例)和类对象本身的传入.因为每次调用函数方法时都会得到一个新的方法对象__get__,所以is失败了.它不是同一个方法对象.

dict.__repr__不是自定义Python函数而是C函数,它的__get__描述符方法基本上只self在类上访问时返回.访问该属性每次都会为您提供相同的对象,因此is可以:

>>> dict.__repr__.__get__(None, dict) is dict.__repr__  # None means no instance
True
Run Code Online (Sandbox Code Playgroud)

方法有一个__func__引用包装函数的属性,用它来测试身份:

>>> OrderedDict.__repr__
<unbound method OrderedDict.__repr__>
>>> OrderedDict.__repr__.__func__
<function __repr__ at 0x102c2f1b8>
>>> OrderedDict.__repr__.__func__.__get__(None, OrderedDict)
<unbound method OrderedDict.__repr__>
>>> OrderedDict.__repr__.__func__ is OrderedDict.__repr__.__func__
True
Run Code Online (Sandbox Code Playgroud)

Python 3取消了未绑定的方法,function.__get__(None, classobj)返回函数对象本身(因此它的行为与此类似dict.__repr__).但是您将看到与实例检索的绑定方法,方法相同的行为.