首先,有两个类变量和两个实例变量的类A
:
In [1]: def fun(x, y): return x + y
In [2]: class A:
...: cvar = 1
...: cfun = fun
...: def __init__(self):
...: self.ivar = 100
...: self.ifun = fun
我们可以看到int类型的类变量和实例变量都可以正常工作:
^{pr2}$但是,如果我们检查函数类型变量,情况就发生了变化:
In [5]: a.ifun, a.cfun
Out[5]:
(<function __main__.fun>,
<bound method A.fun of <__main__.A instance at 0x25f90e0>>)
In [6]: a.ifun(1,2)
Out[6]: 3
In [7]: a.cfun(1,2)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/home/future/<ipython-input-7-39aa8db2389e> in <module>()
----> 1 a.cfun(1,2)
TypeError: fun() takes exactly 2 arguments (3 given)
我知道python已经将a.cfun(1,2)
转换为A.cfun(a,1,2)
,然后引发了错误。在
我的问题是:既然cvar
和cfun
都是类变量,为什么python会以不同的方式处理它们?在
实际上,分配给类成员的函数仍然是函数:
从实例中检索时,它会动态转换为方法对象:
^{pr2}$http://docs.python.org/2/reference/datamodel.html#the-standard-type-hierarchy“用户定义的方法”:
不将转换只发生在指定给该类的函数上。请注意,这在Python3中已经改变了,其中
Class.fun
返回一个普通函数,而不是“unbound method”。在至于为什么需要这样做,方法对象本质上是一个包含函数及其执行上下文(“self”)的闭包。假设您有一个对象,并在某处将其方法用作回调函数。在许多其他语言中,您必须同时传递对象和方法指针或手动创建闭包。例如,在javascript中:
Python在幕后为我们管理:
另一方面,有时在类中使用“裸”函数或“外来”方法是可行的:
上述约定(类vars=>;methods,instance vars=>;functions)为两者提供了一种方便的方法。在
无需添加,就像python中的所有其他东西一样,可以更改这种行为,即编写一个不将其函数转换为方法并按原样返回它们的类。在
相关问题 更多 >
编程相关推荐