Reputation: 1343
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 essentiallyself.hunger
.self.get_hunger()=0
will work for other codes following this task but I don’t understand whyself.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 attributehunger
, 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+=hunger
instead ofself.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 ofhunger
. Can anyone reason with me?
Upvotes: 1
Views: 5200
Reputation: 629
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.
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.
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()
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
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