1

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?

2 Answers 2

2

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()
Sign up to request clarification or add additional context in comments.

8 Comments

@PrashinJeevaganth It shouldn't, I don't think it will. I don't see it anywhere in your code either. Did you do self.get_hunger()==0 instead?
ok nvm, it doesn't work, do u perhaps know the explanation for my 2nd question?
@PrashinJeevaganth It is absolutely allowed to refer to instance attributes directly inside a class, especially inside a setter method, of all things. self.hunger += hunger is fine, and if your professor disagrees then ask them to come see us in chat.stackoverflow.com/rooms/6/python
What is a setter method and under what scenarios is it not allowed to refer to instance attributes? So far I have been dealing with child and parent classes only(maybe a hierarchy of 5 classes), if the parent class of the highest hierarchy doesn't have an adder method, I think I must still refer to the attributes of the parent class inside the child class.
For your set_hunger(self,hunger), can we do instead self.hunger+=hunger, then when we call set_hunger in add_hunger, we can just put argument as hunger instead of self.get_hunger() + hunger. I see from your point that by right I should be hinted to write some kind set_hunger function for a class, so the child classes would not have to touch the attributes of the parent class.
|
1
  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.

1 Comment

Good suggestion on an alternate implementation, I would always want to name the arguments of my methods differently from my attributes if possible, or use references instead of values. However, my homework's requirement is about using an initial value of 0 for hunger attribute, nothing is suggested about a list, and so all the errors relating to copies etc appear.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.