class 中的函数属性

Function's attributes when in a class

我可以使用函数的属性来设置状态标志,例如

def Say_Hello():
    if Say_Hello.yet == True:
        print('I said hello already ...')
    elif Say_Hello.yet == False:
        Say_Hello.yet = True
        print('Hello!')

Say_Hello.yet = False

if __name__ == '__main__':
    Say_Hello()
    Say_Hello()

输出为

Hello!
I said hello already ...

但是,当尝试将函数放在 class 中时,例如

class Speaker:
    def __init__(self):
        pass

    def Say_Hello(self):
        if self.Say_Hello.yet == True:
            print('I said hello already ...')
        elif self.Say_Hello.yet == False:
            self.Say_Hello.yet = True
            print('Hello!')

    Say_Hello.yet = False

if __name__ == '__main__':
    speaker = Speaker()
    speaker.Say_Hello()
    speaker.Say_Hello()

出现这个错误:

Traceback (most recent call last):

  File "...func_attribute_test_class_notworking.py", line 16, in <module>
     speaker.Say_Hello()
  File "...func_attribute_test_class_notworking.py", line 9, in Say_Hello
    self.Say_Hello.yet = True
AttributeError: 'method' object has no attribute 'yet'

在 class 中使用函数属性的正确方法是什么?

Speaker.Say_Hellospeaker.Say_Hello 是两个不同的对象。前者是class语句体中定义的函数:

>>> Speaker.Say_Hello
<function Speaker.Say_Hello at 0x1051e5550>

而后者是 method:

的实例
>>> speaker.Say_Hello
<bound method Speaker.Say_Hello of <__main__.Speaker object at 0x10516dd60>>

此外,每次访问 speaker.Say_Hello 时,您都会得到 method.

不同 实例
>>> speaker.Say_Hello is speaker.Say_Hello
False

您应该改用 self。函数属性更像是一个没有被特别禁止的偶然特性,而不是你应该使用的东西,无论如何。

class Speaker:
    def __init__(self):
        self._said_hello = False

    def Say_Hello(self):
        if self._said_hello:
            print('I said hello already ...')
        else:
            self._said_hello = True
            print('Hello!')

如果您想跟踪 Speakerany 实例是否调用了其 Say_Hello 方法,而不是分别跟踪每个实例,请使用class 属性。

class Speaker:
    _said_hello = False

    def Say_Hello(self):
        if self._said_hello:
            print('Someone said hello already ...')
        else:
            type(self)._said_hello = True
            print('Hello!')