从python 3中的类对象调用成员方法

时间:2019-03-15 14:11:09

标签: python python-3.x

我有这段代码:

class ABC:
    def test():
        print('Hi there')

ABC.test()

哪个输出:

Hi there

这失败了:

ABC().test()
TypeError: test() takes 0 positional arguments but 1 was given
# Makes sense

我们知道,当我们调用classmethod之类的<classname>.<methodname>()时,该类将作为参数隐式传递给它,但是test这里没有任何参数。

为什么由于意外的参数而看不到TypeError?该类不是作为参数传递给test吗?

1 个答案:

答案 0 :(得分:3)

什么都不会传递给test(),因为函数在访问类时不会绑定任何东西。它仍然是 unbound ,您将获得原始功能:

>>> class ABC:
...     def test():
...         print('Hi there')
...
>>> ABC.test
<function ABC.test at 0x1082706c0>

如果您传入正确数量的参数,则可以直接调用函数。此处为0,因此ABC.test()成功。

它不是classmethod,需要用@classmethod装饰(或产生classmethod对象并将其存储为类的属性),然后访问属性将函数绑定到类对象,从而生成绑定的method

>>> class ABC:
...     @classmethod
...     def test():
...         print('Hi there')
...
>>> ABC.test
<bound method ABC.test of <class '__main__.ABC'>>

调用此方法将导致异常:

>>> ABC.test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: test() takes 0 positional arguments but 1 was given

也可以绑定函数,但仅当在类的实例上访问时才可以。 functionclassmethod对象均实现descriptor protocol,并且在类和实例上访问属性将触发描述符上的__get__方法。但是在这种情况下,只有classmethod个对象会返回绑定方法,而函数只会返回自身。

具体来说,将descriptor __get__ method传递给None作为第一个参数,当属性访问在类上时要绑定到的对象,以及在实例上访问时要实例的对象。 classmethod().__get__()忽略实例参数,并生成一个绑定到第二个参数(owner)的方法对象。当第一个参数为self时,函数将返回None,否则将返回绑定到实例的方法对象:

>>> def foo(boundto='nothing'):
...     print(f'Bound to {boundto}')
...
>>> foo.__get__('instance', 'owner')()
Bound to instance
>>> foo.__get__(None, 'owner')()
Bound to nothing
>>> classmethod(foo).__get__('instance', 'owner')()
Bound to owner
>>> classmethod(foo).__get__(None, 'owner')()
Bound to owner