为什么这是错的? `SomeClass.method是SomeClass.method`(Why

2019-10-28 15:04发布

举个例子的代码:

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?

Answer 1:

实施例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__的方法属性。 在这种情况下,它们都是相同的:在__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的“未结合的方法”现在只是一个普通的旧的函数,并通过属性访问检索的实例是相同的类中的字典的对象。 从实施例1结果的变化FalseTrue > Python 3的升级-在Python 2。



文章来源: Why is this false? `SomeClass.method is SomeClass.method`