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

Python-函数作为类属性成为绑定方法,python,methods,class-attributes,Python,Methods,Class Attributes,我注意到,如果我在创建一个类的实例时将一个类属性定义为一个函数,那么该属性将成为一个绑定方法。有人能给我解释一下这种行为的原因吗 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 <__ma

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

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)
[9]中的
:def func():
…:通过
...: 
在[10]中:A类(对象):
..:f=func
....:     
在[11]中:a=a()
In[12]:a.f
出[12]:
在[13]中:a.f()
---------------------------------------------------------------------------
TypeError回溯(最近一次调用上次)
在()
---->1 a.f()
全局a.f=
TypeError:func()不接受任何参数(给定1个)
Python不是基于消息的OO系统1。相反,与JavaScript类似,属性被解析为一级函数,然后被调用;正如所发现的那样,这种行为在力学上有点不同

在Python中,要求方法至少有一个参数,通常称为
self
,当相关实例作为方法调用时,该参数将自动提供给相关实例

此外(也许是问题的关键),Python在建立实例成员绑定时没有区分使用
def..
f=some_func()
;可以说,这与类外的行为相匹配

在本例中,将函数分配给实例“使其被视为实例方法”。在这两种情况下调用的是完全相同的无参数函数;只有将来使用这种方法才相关

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

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

作为演示,以下操作将以同样的方式失败,因为源基础方法不满足接受实例作为参数的最低要求:

g = a.f
g()
在这种情况下,调用
g()
相当于调用
func(a)



1相比之下,Java、C#、Ruby和SmallTalk都是基于消息的OO系统——在这些系统中,对象被告知通过“名称”调用方法,而不是将方法(或函数)解析为可以调用的值。

您将函数分配给属性
a.f
(类
a
的属性
f
)。属性
A.f
被定义为类的一部分。它是一个函数,因此默认情况下是该类的实例方法

创建类
a
的实例(名为
a
)会导致该实例具有属性
f
,您可以通过名称
a.f
访问该属性。这是一个绑定方法(因为它绑定到对象
a
;)

调用每个实例方法时,都会自动接收实例作为其第一个参数(通常称为
self
)。也可以使用其他类型的方法:-请参阅

因此,错误表示
func
不接受任何参数(定义为
def func():
),但收到1(
self

要做您想做的事情,您应该告诉python您正在使用


虽然有点晚了,但另一个可行的解决方案是将函数存储为dictionary,dictionary是类的一个属性

#一些任意函数
def f(x):
返回x
#一个类,它将函数包装为一个dictionary对象,它是一个类attr
课堂测试:
定义初始化(self,f):
self.f={'f':f}
def func(自我,x):
返回self.f['f'](x)
#现在让我们测试测试对象
t=试验(f=f)
t、 func(3)
>>>
3.
这种方法比公认的答案更加冗长,但是,它没有涉及到staticmethod、decorator或其他高级主题。因此,如果您被另一种首选方法所吓倒,这将在紧要关头起作用

编辑:如果您希望它足够健壮,可以处理关键字参数:

类测试:
定义初始化(self,f):
self.f={'f':f}
def func(自我,p):
返回self.f['f'](**p)
def f(**p):
返回p['x']*p['y']
t=试验(f=f)
t、 func({'x':2,'y':3})
>>>
6.
def func():
    pass

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