一个类的方法之间的差异,它们是"功能"哪些是"约束方法"?

时间:2017-08-12 22:29:39

标签: python python-3.x

我做了一点实验。通过检查类或实例的__dict__,我可以看到某些方法具有类型function和一些bound method。实验很乱,我无法解决以下问题。

在Python 3中,类或实例的方法之间有什么区别,它们是" function"哪些是"约束方法"?

他们是如何分别创作的?

它们都可以在类和实例上调用吗?它们是否会被隐含地赋予实例作为第一个参数?

"约束方法"类的属性或类的实例?

感谢。

1 个答案:

答案 0 :(得分:5)

这个答案非常技术性,但我希望它仍然可以理解。问题是需要知道描述符协议才能理解Python中的方法是如何工作的。

Python 3中的所有函数都是descriptors,准确地说它们是非数据描述符。这意味着他们实现了__get__方法 - 但没有__set__方法。

这很有趣,因为如果在类或实例上查找描述符,它们几乎可以做任何事情。

根据Pythons data model__get__方法的定义:

  

object.__get__(self, instance, owner)

     

调用以获取所有者类(类属性访问)或该类的实例(实例属性访问)的属性。 owner始终是所有者类,而instance是访问该属性的实例,或None通过owner访问该属性时。此方法应返回(计算的)属性值或引发AttributeError异常。

那么这与functionbound_method之间的区别有什么关系?

很简单,通过__get__访问instance=None的功能将自行返回:

>>> def func(x): return x
>>> func.__get__(None, object)
<function __main__.func>
>>> func.__get__(None, object) is func
True

如果使用not-None实例访问它将是bound_method

>>> func.__get__(object())
<bound method func of <object object at 0x00000155614A0610>>

它基本上只是存储实例func的包装器:

>>> m = func.__get__(object())
>>> m.__self__   # stored instance
<object at 0x155614a0650>

>>> m.__func__  # stored function
<function __main__.func>

但是,在调用时,它会将实例作为第一个参数传递给包装函数:

>>> m()
<object at 0x155614a0650>

因此,bound method s将实例作为第一个参数传递,而function则不传递(它们需要所有属性)。

因此,当您查看某个类时,所有普通方法将显示为函数,而实例上的所有普通方法将为bound methods

为什么我提到普通的方法?因为您可以定义任意描述符。例如,Python内置函数已经包含几个例外:

  • classmethod
  • staticmethod
  • property(这实际上是一个数据描述符,所以我在下面的讨论中忽略它)
即使在课堂上查找,

classmethod也会显示为bound method。这是因为它们意味着可以在类上调用并将类传递给函数,无论它们是在类还是实例上调用:

class Test(object):
    @classmethod
    def func(x):
        return x

>>> Test.func
<bound method Test.func of <class '__main__.Test'>>
>>> Test().func
<bound method Test.func of <class '__main__.Test'>>

staticmethod始终显示为函数,因为它们从不传递函数的其他内容:

class Test(object):
    @staticmethod
    def func(x):
        return x

>>> Test().func
<function __main__.Test.func>
>>> Test.func
<function __main__.Test.func>

因此,很容易在类上看到bound method(例如classmethod s),同样也可以在实例上找到正常的function(例如{ {1}} S)。