示例 1:
Someclass.a_method
是一个未绑定的方法。这些现在甚至在 Python 中都不存在,所以认为这是一个无用的历史课。
Python 是否会在每次引用该方法时复制该方法?
是的,或多或少。这是通过描述符协议完成的。
>>> SomeClass.a_method # unbound method via attribute access
<unbound method SomeClass.a_method>
>>> SomeClass.__dict__['a_method'] # just stored as a function in the class dict
<function __main__.a_method>
>>> SomeClass.__dict__['a_method'].__get__(None, SomeClass)
<unbound method SomeClass.a_method>
最后一行显示了描述符为访问类的属性而调用的“绑定”操作,但需要手动写出。在纯 Python 中,它是这样的
class Function(object):
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c"
return types.MethodType(self, obj, objtype):
您还可以通过这种方式创建绑定方法:
>>> some_instance = SomeClass()
>>> SomeClass.__dict__['a_method'].__get__(some_instance, SomeClass)
<bound method SomeClass.a_method of <__main__.SomeClass instance at 0xcafef00d>>
示例 2:
方法比较是通过方法上的__func__
和__self__
属性完成的。在这种情况下,它们是相同的: the__func__
是你可以从类 dict 中挖掘出来的相同的普通旧函数,而__self__
is None
。因此,尽管这些方法是不同的对象,但它们比较相等。
示例 3:
正确的。它们是不同的对象,因此并不相同。
示例 4:
如前所述,比较是使用__func__
and__self__
属性。结果与示例 2 不匹配,因为在这种情况下,__self__
属性指的是不同的实例。这些不同的实例不比较相等,因为SomeClass
实例按身份比较,因此方法也不比较相等。
关于当前 Python 版本的最后说明
上面提到的所有内容也适用于当前版本的语言,除了Example 1。在 Python 中,不再有未绑定方法之类的东西,对象模型中这种不必要的复杂性已被删除。
>>> SomeClass.a_method
<function __main__.SomeClass.a_method(self)>
>>> SomeClass.a_method is SomeClass.__dict__['a_method']
True
Python 2 中的“未绑定方法”现在只是一个普通的旧函数,通过属性访问检索到的实例与类 dict 中的对象相同。在 Python 2 -> Python 3 升级中,示例 1结果从False
变为。True