【问题标题】:Why is this false? `SomeClass.method is SomeClass.method`为什么这是假的? `SomeClass.method 是 SomeClass.method`
【发布时间】:2018-04-11 01:20:54
【问题描述】:

以这段代码为例:

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 不匹配?

【问题讨论】:

标签: python python-2.7 python-descriptors


【解决方案1】:

示例 1:

Someclass.a_method 是一个未绑定的方法。这些现在甚至在 Python 中都不存在,所以认为这是一个无用的历史课。

Python 是否在每次引用该方法时都对其进行复制?

是的,或多或少。这是通过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>

最后一行显示了描述符为访问类的属性而调用的“绑定”操作,但需要手动写出。在纯 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__ 是您可以从类字典中挖掘出来的同一个普通旧函数,__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 中的“未绑定方法”现在只是一个普通的旧函数,通过属性访问检索到的实例与类 dict 中的对象相同。 示例 1 结果在 Python 2 -> Python 3 升级中从 False 更改为 True

【讨论】:

    猜你喜欢
    • 2020-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    相关资源
    最近更新 更多