In the following snippet I'm trying to define a factory function which would return objects of different classes derived from Hero based on arguments.
class Hero:
Stats = namedtuple('Stats', ['health', 'defence', 'attack',
'mana', 'experience'])
RaceMaxStats = OrderedDict([
('Knight', Stats(100, 170, 150, 0, inf)),
('Barbarian', Stats(120, 150, 180, 0, inf)),
('Sorceress', Stats(50, 42, 90, 200, inf)),
('Warlock', Stats(70, 50, 100, 180, inf))
])
@staticmethod
def def_race(race: str):
return type(race, (Hero,), {'max': Hero.RaceMaxStats[race]})
Races = OrderedDict([
(race, Hero.def_race(race)) for race in RaceMaxStats.keys()
])
def __init__(self, lord, health, defence, attack, mana, experience):
self.race = self.__class__.__name__
self.lord = lord
self.stats = Hero.Stats(min(health, self.max.health),
min(defence, self.max.defence),
min(attack, self.max.attack),
min(mana, self.max.mana),
min(experience, self.max.experience))
@staticmethod
def summon(race, *args, **kwargs):
return Hero.Races[race](*args, **kwargs)
With the intention of later using it like so:
knight = Hero.summon('Knight', 'Ronald', 90, 150, 150, 0, 20)
warlock = Hero.summon('Warlock', 'Archibald', 50, 50, 100, 150, 50)
The problem is that I cannot initialize the subclasses because Hero is not yet defined:
(race, Hero.def_race(race)) for race in RaceMaxStats.keys()
NameError: name 'Hero' is not defined
Obviously, if I replaced the static method call with the direct type() call I would still need Hero to be defined. My question is how do I best implement this kind of factory. The priority is for the summon() method to retain the same signature, and to return instances of classes derived from Hero.
P.S. none of the code above has ever been run successfully, so it may contain other mistakes.