Search code examples
pythonclassself

Python Newbie - Why does self._ causing a NameError in Python 3


I am attempting to learn how to use classes in Python and have managed to get the following code working through trial and error but am not sure how! It seems the use of 'self.' is sometimes required whilst at other times its use creates an error. I would be be very grateful of someone could explain why the different lines of code seem to behave so differently

If I replace the line self._tot += _new with self._tot += self._new then I get the following error NameError: name 'self' is not defined.

Conversely, if I replace the line self._tot -= self._last with self._tot -= _last then I get the following error NameError: name '_last' is not defined

The code behaving in this seemingly contrary way is:-

class PremiumCounter:   

    def __init__(self, _tot = 0):
        self._tot = _tot        
        self._new = 0
        #self._last = 0

    def add(self, _new = 1):
        self._tot += _new
        self._last = _new

    def undo(self):
        self._tot -= self._last       

    def get_total(self):
        return self._tot

    def clear_counter(self):
        self._tot = 0



ConcertAttendee2 = PremiumCounter(4)#Creates ConcertAttendee2 as an instance of the 'ImprovedCounter' class


ConcertAttendee2.clear_counter()
ConcertAttendee2.add(3)
ConcertAttendee2.add(3)
ConcertAttendee2.undo()
print("Total concert attendees: " + str(ConcertAttendee2.get_total() ))

Solution

  • As @jonrsharpe pointed, in your undo method, you do not have a parameter named _last, therefore you get an error for self._tot -= _last.

    You might get the error self._tot += _new with self._tot += self._new, if you delete self from function argument.

    Also, a python convention: Use underscore for class attributes not for parameters. The code below is better in terms of naming conventions.

    class PremiumCounter:   
    
        def __init__(self, tot = 0):
            self._tot = tot        
            self._new = 0
            #self._last = 0
    
        def add(self, new = 1):
            self._tot += new
            self._last = new
    
        def undo(self):
            self._tot -= self._last       
    
        def get_total(self):
            return self._tot
    
        def clear_counter(self):
            self._tot = 0