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

问题描述 投票:2回答:1

我有这段代码:

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的参数传递的吗?

python python-3.x
1个回答
3
投票

没有任何内容传递给test(),因为函数在访问类时不会绑定任何东西。它仍然是未绑定的,您将获得原始功能:

>>> 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
© www.soinside.com 2019 - 2024. All rights reserved.