1

I am trying to learn Python OOP and have been struggling to understand scope, passing values and how to encapsulate. My earlier attempts have rapidly become spaghetti code (likely because my only programming experience was on 8 bit BASIC 40 years ago), and thus, I am trying classes and objects. Here it is:

import random


class Player:
    def __init__(self, weapon, health):
        self.weapon = weapon
        self.health = health

    def reduce_health(self, amount):
        self.health -= amount

    def check_dead(self):
        if self.health > 0:
            return "Player not dead"
        else:
            return "Player dead"

    def calculate_damage(self, weapon):
        damage_inflicted = random.randint(3, 15) + weapon
        return damage_inflicted

    def fight(self):
        player.reduce_health(self.calculate_damage(self.weapon))
        print(player.health)
        player.check_dead()


player = Player(1, 15)

player.fight()

The calculate_damage function is flagged as being 'static' and the check_dead function seemingly has no effect at all. I need some hints to get my footing. Thanks.

Loris Securo
  • 7,538
  • 2
  • 17
  • 28
misfit138
  • 61
  • 7
  • Could you please clarify what exactly is the question? – Omer Tuchfeld Jun 19 '22 at 11:28
  • 1.The check_dead function ostensibly does nothing; no output and I don't understand why.2. The calculate_damage function is flagged as static in Pycharm. I don't understand why or what that means, as I have no frame of reference from my notes and courses. Thanks. – misfit138 Jun 19 '22 at 11:31
  • 1
    PyCharm is suggesting you make `calculate_damage` a `@staticmethod`, as it makes no use of `Player` or `self`. See https://stackoverflow.com/a/136138/791430 for more information – Omer Tuchfeld Jun 19 '22 at 11:35
  • 2
    `check_dead` returns a string value, it does not output it to stdout. If you want to see the output from `check_dead`, try `print(player.check_dead())` – Omer Tuchfeld Jun 19 '22 at 11:35
  • Thanks. However, I explicitly added (self, weapon) to calculate_damage. Why does it still not 'see' the class or object? – misfit138 Jun 19 '22 at 11:44

2 Answers2

2

There are a few errors in your code.

First, you are using the player variable in the fight function. This works, because you've called the instance of the Player class player, but it wouldn't if you would give it any other name. To fix your issue, use self instead ofplayer in all class functions. The self argument is automatically passed in by python and does always refer to the object on which the the function is called.

Second, the check_deadfunction does nothing because it only returns a value. There is no attribute set or value printed out in this function. In order to make it work, you need to print the value, either inside the function or outside, with the return value of the function.

This code should work:

import random


class Player:
    def __init__(self, weapon, health):
        self.weapon = weapon
        self.health = health

    def reduce_health(self, amount):
        self.health -= amount

    def check_dead(self):
        if self.health > 0:
            return "Player not dead"
        else:
            return "Player dead"

    def calculate_damage(self, weapon):
        damage_inflicted = random.randint(3, 15) + weapon
        return damage_inflicted

    def fight(self):
        self.reduce_health(self.calculate_damage(self.weapon))
        print(player.health)
        print(self.check_dead())


player = Player(1, 15)

player.fight()

In this code, we print the aliveness of the player directly instead of returning it:

import random


class Player:
    def __init__(self, weapon, health):
        self.weapon = weapon
        self.health = health

    def reduce_health(self, amount):
        self.health -= amount

    def check_dead(self):
        if self.health > 0:
            print("Player not dead")
        else:
            print("Player dead")

    def calculate_damage(self, weapon):
        damage_inflicted = random.randint(3, 15) + weapon
        return damage_inflicted

    def fight(self):
        self.reduce_health(self.calculate_damage(self.weapon))
        print(player.health)
        self.check_dead()


player = Player(1, 15)

player.fight()
The_spider
  • 1,202
  • 1
  • 8
  • 18
  • Thank you for your time. I am a long way from proficiency but this allows me progress toward understanding. – misfit138 Jun 19 '22 at 12:04
0

The problem that you are having is probably due to the way you refer to the functions of check_dead(), reduce_health() and the variable health in fight(). You are calling out the player class instance, instead of the instance the function is running in, that meant that, if you were to change the name of the player class instance to something different, it would spill out an error that "player is not defined".
Why the check_dead() is not working could also be because it doesn't print out the values, it just returns them, and it you don't do anything with them when it returns them to the calling function it just scraps them.
I recommend checking the code if it is spelled right and also replace every reference in the class to self. And also make the check_dead() function wrapped in print in the fight() function. That would end up looking something like this:
import random


class Player:
    def __init__(self, weapon, health):
        self.weapon = weapon
        self.health = health

    def reduce_health(self, amount):
        self.health -= amount

    def check_dead(self):
        if self.health > 0:
            return "Player not dead"
        else:
            return "Player dead"

    def calculate_damage(self, weapon):
        damage_inflicted = random.randint(3, 15) + weapon
        return damage_inflicted

    def fight(self):
        self.reduce_health(self.calculate_damage(self.weapon))
        print(self.health)
        print(self.check_dead())


player = Player(1, 15)

player.fight()
   

If this still doesn't work it's propablly of your running environment or your ide/editor.

Also:

Static means, that the function standalone


If a function is static it doesn't use any of the functions/variables the class gives it (which are commonly gotten by using self.[function/variable name]). By that it is independent and it could be written outside of the class and it would still work as intended.
Osensive
  • 9
  • 3
  • In what way does this solve the problem about `self.check_dead()` having no effect? – The_spider Jun 19 '22 at 12:29
  • Sorry i forgot to include it in the answer, now it's there – Osensive Jun 19 '22 at 12:38
  • Thank you for your time. However, I explicitly passed self and weapon to calculate_damage like so, 'calculate_damage(self, weapon)'...so why is calculate_damage static? – misfit138 Jun 19 '22 at 19:57
  • The fact that there's a self argument, doesn't means that the function is not static. Every class method must have a self argument. The thing that makes class methods static, is that they don't use the self argument. – The_spider Jun 24 '22 at 07:47
  • I think I understand. So, even though the self argument is there, I am still referring to it as 'weapon' and not 'self.weapon' – misfit138 Jun 28 '22 at 12:36
  • I have an example to what is static and what not: STATIC: (thats your code)`def calculate_damage (weapon): damage_inflicted = random.randint(3, 15) + weapon return damage_inflicted` Non-STATIC: `def calculate_damage (self): damage_inflicted = random.randint(3, 15) + self.weapon return damage_inflicted` (assuming that self.weapon is the weapon the player is using) Now the key difference is that the Non-STATIC function uses the self.weapon which is a variable from the class not an argument of the function. (also there's no way to add lineBraks so I hope its readable) – Osensive Jun 28 '22 at 13:24