实例变量和函数

时间:2015-08-19 16:43:34

标签: python

我在这里发了帖子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参数。

2 个答案:

答案 0 :(得分:3)

在评估类语句的主体之后,元类将每个函数包装在描述符中,该描述符负责实例,类和静态方法之间的区别。将函数分配给实例属性时,绕过该机制,以便属性引用普通函数对象。

答案 1 :(得分:1)

来自documentation -

  

作为类属性的任何函数对象都为该类的实例定义了一个方法。函数定义没有必要在文本中包含在类定义中:将函数对象赋值给类中的局部变量也是可以的。

这意味着只有分配给类的方法才是类实例的实例方法。

示例 -

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>