3

I'm coding my first python game using OOP and I have some problems with the access to class variables. Specifically, I want to have access to a class variable from a method. For some variables it works, but for a specific boolean variable it does not work:

class Player(object):
    eaten = False

    def __init__(self):
          .....

def eat(Player):
    Player.eaten = True

The problem is that, when the function is called, eaten does not override the variable in the class. For other variables it does correctly what I want though.

EDIT: If, inside a method in the Class player, I add print(self.eaten) after eat() is called, it still prints always False

 class Player(object):
    eaten = False

    def move():
        print(self.eaten)

def eat(Player):
    Player.eaten = True

Thank you!

pfabri
  • 885
  • 1
  • 9
  • 25
maurock
  • 527
  • 1
  • 7
  • 22
  • "[Variables declared inside the class definition, but not inside a method are class or static variables](https://stackoverflow.com/questions/68645/are-static-class-variables-possible)" – Arda Arslan Jul 19 '18 at 13:31
  • 1
    What do you mean by `for other variables it does correctly`? Also are you sure? If I copy and paste your code (giving `__init__` a pass) and call `eat(Player)` then `print(Player.eaten)` I see `True`... – MooingRawr Jul 19 '18 at 13:32
  • Yes I am sure, because inside an additional method in `Player`, when I `print(eaten)` it always prints False, even after `eat()` was called – maurock Jul 19 '18 at 13:50

3 Answers3

5

eaten should be a instance variable, not a class variable - you can have some players eaten and others not, and having it as a class variable means it would affect all players, which is probably not what you want.

class Player(object):
    def __init__(self):
        self.eaten = False

    def move(self):
        if self.eaten:
            print("I have eaten so I can move")
        else:
            print("I can't move! I'm hungry!")

def eat(player, food):
    player.eaten = True # change `eaten` for the player
                        # passed as parameter!

 >>> p = Player() # creates a instance of the Player class
 >>> q = Player() # creates another instance of the Player class
 >>> eat(p, 'apple') # player `p` eates apple
 >>> p.move()
 I have eaten so I can move
 >>> q.move()
 I can't move! I'm hungry!

 print(p.eaten) # will print True
 print(q.eaten) # will print False
nosklo
  • 217,122
  • 57
  • 293
  • 297
  • `def eat()` needs to be outside the class, since I pass actually two classes in it, so I cannot do it inside an other class. It is indeed `def eat(Player, Food)`. – maurock Jul 19 '18 at 13:46
  • @MauroComi ok, I edited my answer, but this is confusing! You should pass instances around, not classes, and you should use lower case variable names for instances. See my answer. – nosklo Jul 19 '18 at 18:10
  • @maurock It may be useful for you to look into [Composition](https://realpython.com/inheritance-composition-python/#whats-composition) – pfabri May 14 '20 at 08:44
1

When you create a class, you want to create instance variables for stuff like this. Instance variables are variables that can be different for each instance of the Class you are creating. You do this by defining it as a variable "self.var" in the init method, like so

class Player(object):
    def __init__(self):
        self.eaten = False

This sets the default value of eaten for every new instance of Player to be False. Whenever we do something like foo = Player(), there is an instance variable like foo.eaten which defaults to being False. Now if we want to update that with a method, we need to reference the instance of Player whose instance variable we are updating, usually with the parameter called self

class Player(object):
    def __init__(self):
        self.eaten = False

    def eat(self):
        self.eaten = True

Now when we do foo.eat(), Python passes in foo as the first parameter to the function eat, meaning self.eaten is really looking at foo.eaten. Therefore when we say self.eaten = True we are setting the instance variable of foo.eaten to True.

Luke
  • 463
  • 3
  • 9
0

When you're calling the function, you're passing an object, not the class. So, you are assigning the variable on the instance. Change your function to

def eat(player): type(player).eaten = True

where type(player) returns the actual Player class

blue_note
  • 27,712
  • 9
  • 72
  • 90