'int' object has no attribute - passing through __call__ to method in class

Viewed 52

What this is: A class uses to control game characters stats and interaction for both NPCs and players.

The call method was added to create mew "mob types" that can have their stat scaling controlled based on the player level.

I am trying to use the Mob.wyvern(player_level) method to create a "Wyvern" type NPC. In this case the code flows successfully until we try to modify a_wyvern.life using the self.playerlevel call.

Error:

Traceback (most recent call last):
  File "c:\Users\User\mystuff\Classes Game\Characters.py", line 74, in <module>
    a_wyvern = Mobs.wyvern(player_level)
  File "c:\Users\User\mystuff\Classes Game\Characters.py", line 36, in wyvern
    a_wyvern.life += a_wyvern.player_level
AttributeError: 'Mobs' object has no attribute 'player_level'
#Initializer, passing variables to all 
class Mobs():
    def __init__(self):
        self.life = 10
        self.atk = 2
        self.arm = 1
        self.name = villains.gen()
        self.playername = heroes.gen()
        self.type = type
            
    def __call__(self, player_level):
        self.player_level = player_level
        pass

    def attack(self, enemy):
        damage_amount = enemy.take_damage(self.atk)
        return damage_amount

    def take_damage(self, amount):
        damage_amount = (amount - self.arm)
        self.life -= damage_amount
        return damage_amount

    
    def wyvern(self):
        a_wyvern = Mobs()
        a_wyvern.type = "Wyvern"
        a_wyvern.life += self.player_level
        return a_wyvern
player_level = 20

a_wyvern = Mobs.wyvern(player_level)
a_wyvern.type
a_wyvern.life
a_wyvern.atk

print(a_wyvern.life)
print(a_wyvern.atk)
print(a_wyvern.name)
2 Answers

From what I can see, you've got the wrong idea about call. After you create an instance of a class, calling that instance like a function will be when __call__ runs. Example:

>>> class A:
    def __init__(self, A):
        print('A', A)
        
    def __call__(self, B):
        print('B', B)

        
>>> a = A(5)
A 5
>>> a(4)
B 4

Call never actually runs in your scenario. Instead, you're bypassing __init__ and __call__, to run a separate, initialization function, wyvern.

The problem here is one of two things. First, call never runs, despite it being crucial to wyvern's execution. Second, you pass an integer into wyvern. self is a function variable, that automatically gets replaced by the instance of the class that each function is running in. An integer is a different class, that does not have an internal variable called player_level.

To sum up, your class initialization is messed up, which is creating a bunch of errors for you

I think you forgot to save the file since the error says a_wyvern.life += a_wyvern.player_level, but your code says a_wyvern.life += self.player_level.

Related