问题 Python - 作为类属性的函数成为绑定方法


我注意到,如果我在创建该类的实例时定义一个等于函数的类属性,该属性将成为绑定方法。有人能解释一下这种行为的原因吗?

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)

4663
2018-02-10 17:17


起源



答案:


您为该属性分配了一个函数 f。因为函数现在在类中它变成了一个方法,特别是一个绑定方法(因为它与对象有界, 这里进一步说明)。

类中的方法至少接收一个参数(self),除非特别说明不 - 看 类方法和静态方法  - 因此错误说明了这一点 func 不带参数(因为它被定义为 def func():)但收到1(self

要做你想做的事,你应该告诉python你正在使用a 静态方法

def func():
    pass

class A(object):
    f = staticmethod(func)

8
2018-02-10 18:01





Python是  基于消息的OO系统1。相反,类似于JavaScript,属性被解析为第一类函数然后被调用;正如所发现的那样,这种行为在机制上有所不同。

在Python中,要求是方法至少有一个参数,通常称为 self,这将自动提供相关的实例 什么时候 它被调用为一种方法。

此外(也许到了问题的关键点),Python没有区分使用 def f.. 要么 f = some_func() 建立实例成员绑定时;可以说这匹配了类之外的行为。

在该示例中,将函数分配给实例'使其期望被视为实例方法'。在两种情况下都调用完全相同的无参数函数;只有未来的使用才是相关的。

现在,与JavaScript不同,Python通过绑定方法的概念处理方法和对象关联 - 作为方法解析的函数总是“绑定”。

的行为 a.f 返回绑定方法 - 将自动将绑定对象提供给第一个参数的函数 self  - 独立于功能的来源完成。在这种情况下,这意味着无参数函数在被“绑定”时不能使用,因为它不接受a self 参数。

作为演示,以下将以相同的方式失败,因为源底层方法可以  满足接受实例作为参数的最低要求:

g = a.f
g()

在这种情况下打电话 g() 相当于打电话 func(a)


1 为了比较,Java,C#,Ruby和SmallTalk是基于消息的OO系统 - 在这些系统中,一个对象被告知通过'name'调用方法,而不是将方法(或函数)解析为可以调用的值。


1
2018-02-10 17:24