Prashin Jeevaganth
Prashin Jeevaganth

Reputation: 1343

Python: Same name for class method parameters and class attribute

I have an assignment on classes. One of my tasks is as follows:

a. Augment the Tribute class by adding a new property, hunger, which will describe the level of hunger for the Tribute. The initial value for hunger should be 0, as all the Tributes will start the game with full stomach.

b. Create a method, get_hunger(), which return the current hunger level of the tribute.

c. Create a method, add_hunger(hunger), which will add a hunger value to the Tribute’s hunger. When the hunger of a Tribute is equal or more than 100, he/she will go_to_heaven(). (FYI go_to_heaven() is defined previously by other parent classes)

1)I wrote the following code, and when I tried running it I keep getting syntax error highlighted on the indentation right before self.get_hunger()+=hunger. May I know the reason for the syntax error since .get_hunger() is essentially self.hunger. self.get_hunger()=0 will work for other codes following this task but I don’t understand why self.get_hunger()+=hunger wont work. My lecturer stresses on not breaking the underlying layer of abstraction, which is why I would use the method .get_hunger() over attribute hunger, especially if I needed to get hunger value from instances of future child classes of Tribute, not sure if this concept is also embraced in practical situations.

class Tribute(Person):
    def __init__(self, name, health):
        super().__init__(name, health, -1)
        self.hunger=0

    def get_hunger(self):
        return self.hunger

    def add_hunger(self,hunger):
        self.get_hunger()+=hunger  #dk why can't assign to function call
        if self.get_hunger()>=100:
            self.go_to_heaven()

2)I also tried writing self.hunger+=hungerinstead of self.get_hunger()+=hunger to get past the syntax error and it works.However, I don’t find it intuitive why when defining a class method, and when I face a scenario where the name of the method parameter and the name of the class attribute is the same, the parameter will not overwrite the attribute in the form of hunger. Can anyone reason with me?

Upvotes: 1

Views: 5200

Answers (2)

Constantine Ketskalo
Constantine Ketskalo

Reputation: 629

  1. Looks like you have abstraction already, since you're using a method to increase class field add_hunger() with health checking inside. Not using class field directly inside it's own method doesn't seem to have much sense.

  2. You can't access class field self.hunger by using its method self.get_hunger().

    Your method self.get_hunger() returns value of self.hunger (its copy), but not the variable itself. So you can add any number to that value, but you need to write it somewhere to keep its value. So, when you run self.get_hunger()+=hunger your method returns a copy of self.hunger, adds hunger from parameters to it and then this copy is lost, but self.hunger is the same.

    So, if you want to increase self.hunger - you just need to use self.hunger+=hunger, which you checked already.

  3. It would actually work if you would use the type of variable, that is passed by reference, not by value. Like list in this example, but I'd say it's kind of a perverted way to do so. ;)

     class Tribute(Person):
         def __init__(self, name, health):
             super().__init__(name, health, -1)
             self.hunger=[0]
    
         def get_hunger(self):
             return self.hunger
    
         def add_hunger(self,hunger):
             self.get_hunger()[0]+=hunger  # dk why can't assign to function call
             if self.get_hunger()[0]>=100:
                 self.go_to_heaven()
    
  4. Using the same names for different things is not good. It can cause some errors. Even if one of them is variable and another one is method. If you try to pass that method to some thread later - it will never know which one you're passing there. If all names are different - it's safe and more readable.

Upvotes: 1

cs95
cs95

Reputation: 402523

Assignments are performed on variables. That's just how Python works. Variables are references to objects in memory.

Function calls return objects, and you can't assign to an object.


I recommend using a setter method to handle the other side of the abstraction.

class Tribute(Person):
    ...

    def get_hunger(self):
        return self.hunger

    def set_hunger(self, hunger):
        self.hunger = hunger

    def add_hunger(self,hunger):
        self.set_hunger(self.get_hunger() + hunger)
        if self.get_hunger() >= 100:
            self.go_to_heaven()

Upvotes: 2

Related Questions