Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function's attributes when in a class

I can use a function's attribute to set a status flag, such as

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()

and the output is

Hello!
I said hello already ...

However, when trying to put the function in a class, like

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()

There is this error:

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'

What is the proper way to use function's attribute in a class?

like image 565
Jen-Feng Hsu Avatar asked Mar 07 '26 10:03

Jen-Feng Hsu


1 Answers

Speaker.Say_Hello and speaker.Say_Hello are two different objects. The former is the function defined in the body of the class statement:

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

while the latter is an instance of method:

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

Further, every time you access speaker.Say_Hello, you get a different instance of method.

>>> speaker.Say_Hello is speaker.Say_Hello
False

You should just use self instead. Function attributes are more of an accidental feature that isn't specifically prohibited rather than something you should use, anyway.

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!')

If you want to track if any instance of Speaker has called its Say_Hello method, rather than tracking this for each instance separately, use a class attribute.

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!')
like image 79
chepner Avatar answered Mar 08 '26 22:03

chepner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!