Reputation: 23
I'm trying to generate a name for each Goblin object, but either they all have the same name or this error happens
import random
max_enemies = 5
class Entity():
def __init__(self, name, max_hp, min_hp, attack_dmg):
self.name = name
self.max_hp = max_hp
self.min_hp = min_hp
attack_dmg = attack_dmg
class Goblin(Entity):
def __init__(self):
super().__init__()
Enemies = []
def enemy_spawner():
for x in range(max_enemies):
random_name_gen = random.randint(1, 10)
Enemies.append(Goblin(random_name_gen))
enemy_spawner()
for x in range(len(Enemies)):
print(Goblin.name)
The error
AttributeError: type object 'Goblin' has no attribute 'name'
I've tried making Goblin it's own class with a name but it didn't work either
Upvotes: 2
Views: 924
Reputation: 54183
Your code doesn't produce the same error you posted, getting instead:
>>> enemy_spawner()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in enemy_spawner
TypeError: __init__() takes 1 positional argument but 2 were given
That's expected though, because while your structure is good it's missing a key bit of boilerplate to make it work -- you need to pass the list of arguments down to the superclass's constructor. Try this instead:
class Goblin(Entity):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Or indeed simply omit the __init__
method entirely!
class Goblin(Entity):
pass
Also: to do the printing, you'll have to reference the Goblin instance instead of the Goblin class.
for enemy in Enemies:
print(enemy.name)
Might I suggest a different way, though? Consider building a constructor inside Entity
that produces a Goblin with a random name!
class Entity:
# As above
def __init__(self, *args, **kwargs):
self.name = name
self.max_hp = max_hp
self.min_hp = min_hp
attack_dmg = attack_dmg
# this is new!
@classmethod
def with_random_name(cls, name_generator=some_name_generator_function, *args, **kwargs):
return cls(name=name_generator(), *args, **kwargs)
# Set some default values if all goblins should be the same
class Goblin(Entity)
min_hp, max_hp = 5, 10 # or whatever
attack_damage = 2 # or whatever
def __init__(self, name, min_hp, max_hp, attack_damage, *args, **kwargs):
super().__init__(*args,
min_hp=self.min_hp,
max_hp=self.max_hp,
attack_damage=self.attack_damage,
**kwargs)
This will let you do:
for _ in range(num_enemies):
enemy = Goblin.with_random_name()
enemies.append(enemy)
Upvotes: 2
Reputation: 71570
You could try adding *args
to __init__
. And also just getting the name
attribute from the actual values from the Enemies
list:
import random
max_enemies = 5
class Entity():
def __init__(self, name, max_hp=None, min_hp=None, attack_dmg=None):
self.name = name
self.max_hp = max_hp
self.min_hp = min_hp
attack_dmg = attack_dmg
class Goblin(Entity):
def __init__(self, *args):
super().__init__(*args)
Enemies = []
def enemy_spawner():
for x in range(max_enemies):
random_name_gen = random.randint(1, 10)
Enemies.append(Goblin(random_name_gen))
enemy_spawner()
for x in Enemies:
print(x.name)
Example output:
10
9
9
6
2
Upvotes: 1