我注意到,如果我定义一个类属性等于一个函数,那么当我创建该类的实例时,这个属性就变成了一个绑定方法。谁能给我解释一下这种行为的原因?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | In [9]: def func(): ...: pass ...: In [10]: class A(object): ....: f = func ....: In [11]: a = A() In [12]: a.f Out[12]: <bound method A.func of <__main__.A object at 0x104add190>> In [13]: a.f() --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-13-19134f1ad9a8> in <module>() ----> 1 a.f() global a.f = <bound method A.func of <__main__.A object at 0x104add190>> TypeError: func() takes no arguments (1 given) |
您为属性
类中的方法接收至少一个参数(
要做您想做的事情,您应该告诉python您正在使用一个静态方法
1 2 3 4 5 | def func(): pass class A(object): f = staticmethod(func) |
Python不是一个基于消息的OO系统1。相反,与JavaScript类似,属性被解析为一级函数,然后调用;这种行为在发现的这类机制中略有不同。
在Python中,要求方法至少有一个参数,通常称为
此外(也许就问题的重点而言),Python在建立实例成员绑定时没有区分使用
在本例中,将函数赋值给实例"使它期望被当作实例方法对待"。在这两种情况下,它是完全相同的——无参数的——函数;只有将来才会用到它。
现在,与JavaScript不同,Python通过绑定方法的概念处理方法和对象关联——函数解析为方法总是"绑定"的。
作为演示,下面的方法也会以同样的方式失败,因为源底层方法不满足接受实例作为参数的最低要求:
1 2 | g = a.f g() |
在这种情况下,调用
为了便于比较,Java、c#、Ruby和SmallTalk都是基于消息的OO系统——在这些系统中,对象被告知使用"name"调用方法,而不是将方法(或函数)解析为可调用的值。