为什么这是错误的? `SomeClass.method 是 SomeClass.method`
Why is this false? `SomeClass.method is SomeClass.method`
以这段代码为例:
class SomeClass():
def a_method(self):
pass
print(SomeClass.a_method is SomeClass.a_method) # Example 1: False
print(SomeClass.a_method == SomeClass.a_method) # Example 2: True
print(SomeClass().a_method is SomeClass().a_method) # Example 3: False
print(SomeClass().a_method == SomeClass().a_method) # Example 4: False
- 示例1:我猜他们是同一个对象。 Python 是否在每次引用方法时都复制该方法?
- 示例 2:预期。
- 示例 3:符合预期,因为它们是不同的对象。
- 示例 4:为什么此输出与示例 2 不匹配?
示例 1:
Someclass.a_method
是一个 未绑定方法 。现在 Python 中甚至都不存在这些,因此请将其视为无用的历史课。
Does Python make a copy of the method each time it is referenced?
是的,或多或少。这是通过 descriptor protocol 完成的。
>>> 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>
最后一行显示了描述符为 class 上的属性访问调用的 "binding" 操作,但手动写出。在纯 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__
属性完成的。在这种情况下,它们是相同的:__func__
是您可以从 class 字典中挖掘出的相同的普通旧函数,而 __self__
是 None
。因此,尽管这些方法是不同的对象,但它们比较相等。
示例 3:
正确。它们是不同的对象,因此并不相同。
示例 4:
如前所述,比较是使用 __func__
和 __self__
属性。结果与示例 2 不匹配,因为在本例中,__self__
属性引用不同的实例。这些不同的实例比较不相等,因为 SomeClass
个实例按身份进行比较,因此这些方法也不相等。
关于 Python
当前版本的最后说明
除了示例 1,上面提到的所有内容也适用于该语言的当前版本。在 Python 中,不再有未绑定方法这样的东西,对象模型中这种不必要的复杂化已被删除。
>>> SomeClass.a_method
<function __main__.SomeClass.a_method(self)>
>>> SomeClass.a_method is SomeClass.__dict__['a_method']
True
Python 2 中的 "unbound method" 现在只是一个普通的旧函数,通过属性访问检索的实例与 class 字典中的对象相同。 示例 1 结果在 Python 2 -> Python 3 升级中从 False
更改为 True
。
以这段代码为例:
class SomeClass():
def a_method(self):
pass
print(SomeClass.a_method is SomeClass.a_method) # Example 1: False
print(SomeClass.a_method == SomeClass.a_method) # Example 2: True
print(SomeClass().a_method is SomeClass().a_method) # Example 3: False
print(SomeClass().a_method == SomeClass().a_method) # Example 4: False
- 示例1:我猜他们是同一个对象。 Python 是否在每次引用方法时都复制该方法?
- 示例 2:预期。
- 示例 3:符合预期,因为它们是不同的对象。
- 示例 4:为什么此输出与示例 2 不匹配?
示例 1:
Someclass.a_method
是一个 未绑定方法 。现在 Python 中甚至都不存在这些,因此请将其视为无用的历史课。
Does Python make a copy of the method each time it is referenced?
是的,或多或少。这是通过 descriptor protocol 完成的。
>>> 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>
最后一行显示了描述符为 class 上的属性访问调用的 "binding" 操作,但手动写出。在纯 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__
属性完成的。在这种情况下,它们是相同的:__func__
是您可以从 class 字典中挖掘出的相同的普通旧函数,而 __self__
是 None
。因此,尽管这些方法是不同的对象,但它们比较相等。
示例 3:
正确。它们是不同的对象,因此并不相同。
示例 4:
如前所述,比较是使用 __func__
和 __self__
属性。结果与示例 2 不匹配,因为在本例中,__self__
属性引用不同的实例。这些不同的实例比较不相等,因为 SomeClass
个实例按身份进行比较,因此这些方法也不相等。
关于 Python
当前版本的最后说明除了示例 1,上面提到的所有内容也适用于该语言的当前版本。在 Python 中,不再有未绑定方法这样的东西,对象模型中这种不必要的复杂化已被删除。
>>> SomeClass.a_method
<function __main__.SomeClass.a_method(self)>
>>> SomeClass.a_method is SomeClass.__dict__['a_method']
True
Python 2 中的 "unbound method" 现在只是一个普通的旧函数,通过属性访问检索的实例与 class 字典中的对象相同。 示例 1 结果在 Python 2 -> Python 3 升级中从 False
更改为 True
。