1

So when i change variable health im trying to inform user that their health has changed by printing "Your health is %s". Heres how it looks like...

health=5

def start():         
  global health
  health+=2

So I'm wondering is there a way to inform the user with some kind of overarching function that is not within this function start() but outside it so that every time variable health is changed it prints that and that? I'm learning python so dont judge!

timgeb
  • 76,762
  • 20
  • 123
  • 145
  • 2
    Easiest way is probably to make a function to change health, which makes the adjustment to the value and then does whatever other stuff you want to do. Then call this function whenever health changes, rather than directly mutating the value. (PS if this project gets to any size you'll be much better off doing it with classes than with global functions/variables) – Robin Zigmond Sep 23 '18 at 20:24
  • Thanks i will try it that way for sure! It makes more sense since it just complicates stuff this way! Im new so i thought there is something that solves it easily! – Milan Rasovic Sep 23 '18 at 22:45

4 Answers4

3

We can do better than what you are trying to do by having a Player class with a custom __setattr__ hook.

class Player:
    def __init__(self):
        vars(self)['health'] = 100 # suppress __setattr__

    def __setattr__(self, attr, value):
        if attr == 'health':
            print('health changed to {}'.format(value))
        super().__setattr__(attr, value)

Of course, you can expand this class according to your needs. For example, you could add a name attribute and print '{}'s health changed to {}'.format(self.name, value).

Demo:

>>> p = Player()
>>> p.health
100
>>> p.health += 2
health changed to 102

As a bonus, you now can have multiple players with different health levels at the same time and don't have to manage global variables.

timgeb
  • 76,762
  • 20
  • 123
  • 145
  • This is probably the better solution, but for the OP's purpose it seems a little overkill, especially since he/she is new to Python, this may be out of the scope of his/her understanding. – N Chauhan Sep 23 '18 at 20:44
  • @NChauhan I share your concern, however the answers at stackoverflow are for all future readers of the question, including the future version of OP! – timgeb Sep 23 '18 at 20:45
  • Isn't properties maybe a better solution? Then you don't need too handle all the attributes individually so if you decide to add more attributes to the Player-class it won't be so much if a hassle. – Alexander Simko Sep 23 '18 at 20:53
  • 1
    @AlexanderSimko properties are better when you need the getter. See [this](https://stackoverflow.com/questions/17576009/python-class-property-use-setter-but-evade-getter) answer. – timgeb Sep 23 '18 at 21:19
  • No worries thanks i will try to understand, im learning from "Learn python the hard way" it is encouraged to seek new stuff and try to understand it although i thought there is some simple answear... – Milan Rasovic Sep 23 '18 at 22:38
2

I think the easiest way is to define a function somewhere in your code:

health = 5
def main():
    global health
    def change_health(amount):
        health += amount
        print('your health went {} by {}'
              .format('up' if amount > 0 else 'down',
                      abs(amount)))

    change_health(-2)

This function uses the global variable health and changes it. Then as described, it prints out that message. The line 'up' if amount > 0 else 'down' I thought was quite nifty: it results in either up or down being formatted depending if the number is positive or not.

The format string means each {} will be replaced with whatever value is put in the .format() call in their respective positions.

N Chauhan
  • 3,407
  • 2
  • 7
  • 21
0
health=5

def start():
    new_health= health +2
    print new_health, health

I believe this is what you are looking for. Since the your variable is global it could be changed anywhere in the your programme.So by printing both you can see that your original health does not change.

Shyryu
  • 139
  • 1
  • 1
  • 9
0

We can create a subtype of int.

class Health(int):
    def __new__(cls, value):
        return int.__new__(cls, value)
    def __iadd__(self, other):
        print(f"+{other} health")
        return self.__class__(self + other)
    def __isub__(self, other):
        print(f"-{other} health")
        return self.__class__(self - other)

This is a bit complicated, but an interesting ability.

In [1]: h = Health(10)

In [2]: h += 2
+2 health

In [3]: h -= 3
-3 health

In [4]: h
Out[4]: 9

But i prefer the approach of @timgeb

Artemij Rodionov
  • 1,721
  • 1
  • 17
  • 22