我在这里发了帖子functions and class attributes (python)
定义时 一个class属性并给它一个这样的函数:
示例1
def add_age(cls,age):
cls.yrs_old = age
return cls
class Test:
age = add_age
a = Test()
a.age(5)
print(a.yrs_old)
self
自动作为add_age
函数的第一个参数传递。
然而,玩弄它更多地做同样的事情 但这次将函数作为实例属性传递,如下所示:
示例2
def test_func(self):
self.class_attribute = "test"
class Test:
def __init__(self,func):
self.func = func
a = Test(test_func)
print(a.func())
链接帖子中的答案表明functions
中的所有class
都会自动传递self
,如果class
实例化如下:
a = Test(test_func)
现在奇怪的是,如果我将test_func
放在一个类属性中,就像我的第一个例子一样。
如果你在构造函数/ init中传递函数,就像这样:
def test_func(self):
self.class_attribute = "test"
class Test:
def __init__(self,func):
self.func = func
并将其称为:
a = Test(test_func)
print(a.func())
a.func
突然表现得像静态方法而不是示例1 ,其中在class属性中定义的函数成为常规类方法。
发生了什么事??
我认为类中的所有函数都隐式传递了self
参数。
答案 0 :(得分:3)
在评估类语句的主体之后,元类将每个函数包装在描述符中,该描述符负责实例,类和静态方法之间的区别。将函数分配给实例属性时,绕过该机制,以便属性引用普通函数对象。
答案 1 :(得分:1)
作为类属性的任何函数对象都为该类的实例定义了一个方法。函数定义没有必要在文本中包含在类定义中:将函数对象赋值给类中的局部变量也是可以的。
这意味着只有分配给类的方法才是类实例的实例方法。
示例 -
On Error GoTo errHandler:
Application.EnableCancelKey = xlErrorHandler
ActiveWorkbook.Save
Application.EnableCancelKey = xlInterrupt
exitHere:
Exit Sub
errHandler:
If MsgBox("something", vbOKCancel) = vbCancel Then
Application.EnableCancelKey = xlInterrupt
Exit Sub
End If
Resume
但是,只要为实例变量分配单独的函数对象,它就不再是实例方法,因为未在类级别定义,它仅为该特定实例定义,例如 -
>>> class A:
... def a(self):
... print("Hmm")
...
>>> b = A()
>>> b.a()
Hmm
>>> b.a
<bound method A.a of <__main__.A object at 0x006D13D0>>
正如您所看到的,当您直接将函数分配给实例变量时(而不是将其分配给类变量,它现在是一个普通的实例属性,它引用一个函数对象,而不是一个实例方法。
您还可以在定义类之后将函数赋值给类变量,并且实例会自动将它们作为实例方法获取,例如 -
>>> def c():
... print("Hello")
...
>>> b.a = c
>>> b.a()
Hello
>>> b.a
<function c at 0x0017B198>