0

We need a way for our Tribute object to reduce their hunger. Create a method eat(food), which takes in a Food object. It will reduce the hunger of the player by the food.get food value(). If object that's passed to the eat method is of the type Medicine, it will increment the player’s health by medicine.get medicine value().

Pre-defined code:

class Tribute(Person):
    def reduce_hunger(self, hunger):
        self.hunger = self.hunger - hunger
        if self.hunger < 0:
            self.hunger = 0
        else:
            return self.hunger

class Thing(MobileObject):
    def __init__(self, name):
        super().__init__(name, None)
        self.owner = None 

    def set_owner(self, owner):
        self.owner = owner

    def get_owner(self):
        return self.owner

    def is_owned(self):
        return self.owner is not None

class Person(LivingThing):
   def take(self, thing):
    # Can only take things in current location and not owned by others
        if isinstance(thing, Thing) and thing in self.place.objects and not thing.is_owned():
            thing.set_owner(self)
            self.inventory.append(thing)
            self.place.del_object(thing)
            GAME_LOGGER.add_event("TOOK", self, thing)
        else:
            GAME_LOGGER.warning("{} cannot take {}.".format(self.get_name(), thing.get_name()))

def named_col(col):
    # Only accepts tuple/list
    type_col = type(col)
    if type_col != list and type_col != tuple:
        return None

    return type_col(map(lambda x: x.get_name() if isinstance(x, NamedObject) else x, col))

class Food(Thing):
    def __init__(self, name, food_value):
        self.name = name
        self.food_value = food_value
    def get_food_value(self):
        return self.food_value


class Medicine(Food):
    def __init__(self, name, food_value, medicine_value):
        super().__init__(name, food_value)
        self.medicine_value = medicine_value
    def get_medicine_value(self):
        return self.medicine_value

class MobileObject(NamedObject):
    def __init__(self, name, place):
        super().__init__(name)
        self.place = place

    def get_place(self):
        return self.place

This is my code:

def eat(self, food):
    if food in self.get_inventory():
        self.inventory.remove(food) # not self.inventory = self.inventory.remove(food) cos self.inventory is a list. if use = it wont return anything
        self.reduce_hunger(food.get_food_value())
        if isinstance(self, medicine):
            self.health = self.health + food.get_medicine_value()
            if self.health > 100:
                self.health = 100
            elif self.health <0:
                self.health = 0

To test my code:

cc = Tribute("Chee Chin", 100)
chicken = Food("chicken", 5)
cc.take(chicken)                        # Chee Chin took chicken
cc.take(aloe_vera)                      # Chee Chin took aloe vera
print(named_col(cc.get_inventory()))    # ['chicken', 'aloe vera']

i got this error:

AttributeError: 'Food' object has no attribute 'owner' 

instead of the expected output 'Chee Chin took chicken'.

What's wrong with my code?

1 Answers1

2

Food is a subclass of Thing but Food's __init__ doesn't call Thing's __init__. That is the source of the problem. Food's __init__ needs the following line at its start:

super().__init__(name)
Dan D.
  • 73,243
  • 15
  • 104
  • 123
  • Furthermore, now that the superclass `__init__()` is being called, the `self.name = name` line is no longer needed in `Food`. – Edwin S. Apr 09 '14 at 14:49
  • You use `super()` when you need to initialize variables that exist in a parent class. "Okay, so how do I know when I need to do that?", you might ask. Easy! In every subclass you create. Basically, `super().__init__()` should be the first executable line in *any* subclass' `__init__()`. (Just pass in the variables that need to be sent to the parent. In this case, `name`.) I would suggest you bookmark [this post on Python inheritance](http://stackoverflow.com/questions/576169/understanding-python-super-and-init-methods) and refer to it periodically. – Edwin S. Apr 09 '14 at 15:20