Reputation: 175
I have two pretty simple classes written below. Human
inherits from the Mammal
class. When I call print(jo.drinkMe("sage"))
, I expect "sick" to be printed, but "fine" is printed. I think that self.problem
in the Human
class overwrites self.problem
in the Mammal
class. What do I need to do to my code in order for the print statement at the end to print "sick"?
class Mammal:
def __init__(self):
self.problem = "sage"
self.result = "sick"
def drinkMe(self,tea):
if tea == self.problem:
return self.result
else:
return "fine"
class Human(Mammal):
def __init__(self):
super().__init__()
self.problem = "paint"
self.result = "die"
def drinkMe(self,tea):
if tea == self.problem:
return self.result
else:
return super().drinkMe(tea)
jo = Human()
to = Mammal()
print(jo.drinkMe("sage"))
Upvotes: 0
Views: 144
Reputation: 175
I found a pretty simple way to prevent the instance variables declared in Human
from overriding those in Mammal
. The code basically just reassigns the values of self.problem
and self.result
each time drink_me
is called:
class Mammal:
def __init__(self):
self.problem = "sage"
self.result = "sick"
def drinkMe(self,tea):
if tea == self.problem:
return self.result
else:
return "fine"
class Human(Mammal):
def __init__(self):
super().__init__()
self.problem = "paint"
self.result = "die"
def drinkMe(self,tea):
result = ''
if tea == self.problem:
return self.result
else:
super().__init__()
result = super().drinkMe(tea)
self.__init__()
return(result)
jo = Human()
print(jo.drinkMe("sage"))
print(jo.drinkMe("paint"))
This code first prints 'sick' and then 'die'.
Upvotes: 0
Reputation: 1221
I hope this helps. It is a little different way of thinking than your original code, but honestly the code you posted was going to require some messy super()
calls. I think that what you're aiming for is a subclass of Mammal()
with additional options for a result from drinkMe()
What about taking this approach: All Mammals
now have a dictionary with drinks and results. Subclasses update this dictionary with their own custom responses to the drink. This way you have a single function that just returns the response for a drink. What should happen if an instance drinks something that does not have a response set? Now you only need to add exception handling once inside drinkMe()
.
class Mammal:
def __init__(self):
self.problems = {'sage': 'sick'}
def drinkMe(self, tea):
return self.problems[tea]
class Human(Mammal):
def __init__(self):
super().__init__()
self.problems.update({'paint': 'die'})
jo = Human()
print(jo.drinkMe("sage"))
Edit: To comment more on why your original code printed fine
instead of sick
.
When you instatiated a Human
called jo
, jo.problem
is set to paint
. So, jo.drinkMe
calls super.drinkMe
which again checks if tea == self.problem
. But remember, you still have not changed jo.problem
. It is still set to paint
, and so fine
gets returned.
self
is the instance itself, in this case it is jo
and when you call the super.drinkMe()
, super.__init__()
is not run again, so self.problem
is still set to whatever it was.
Upvotes: 2
Reputation: 54273
The problem you're having is that Mammal
only sets its instance attributes problem
and result
when it's instantiated. jo = Human()
instantiates a Mammal
object, but then clobbers the problem
and result
attributes into its own. To be verbose, you have:
class Human(Mammal):
def __init__(self):
super().__init__()
# calls `Mammal.__init__()`, which sets
# self.problem = "sage"
# self.result = "sick"
self.problem = "paint"
self.result = "die"
# overwrites what `Mammal.__init__()` did a
# couple lines ago.
...
You might instead do:
class Mammal(object):
problem = "sage"
result = "sick"
def drink_me(self, tea):
if tea == self.problem:
return self.result
else:
return "fine"
class Human(Mammal):
problem = "paint"
result = die
def drink_me(self, tea):
if tea == self.problem:
return self.result
else:
return super().drink_me(tea)
Upvotes: 2