Simply put, you override Wand.__init__
in a class that inherits from it, so CastSpell.wandtype
never installed in CastSpell
. In addition, my_wand
cannot pass information to cast_spell
, so you are confused about the role of inheritance.
No matter how you do it, you need to somehow go through length
and wandtype
to CastSpell
. One way is to include them directly in CastSpell.__init__
:
class CastSpell(Wand): def __init__(self, spell, thing, length, wandtype): self.spell = spell self.thing = thing self.length = length self.wandtype = wandtype
Another, more general way would be to pass these two into the base __init__()
native class:
class CastSpell(Wand): def __init__(self, spell, thing, length, wandtype): self.spell = spell self.thing = thing super(CastSpell, self).__init__(length, wandtype)
Another way would be to stop CastSpell
inheritance from Wand
(is CastSpell
a kind of Wand
? Or something a Wand
?) And instead make each Wand have the ability to have CastSpell
in it: instead of "is-a" (a CastSpell
is a kind of Wand
), try "has-a" (a Wand
has Spell
s).
Here's a simple, not-so-good way to have Wand stock spells:
class Wand(object): def __init__(self, wandtype, length): self.length = length self.wandtype = wandtype self.spells = {} # Our container for spells. # You can add directly too: my_wand.spells['accio'] = Spell("aguamenti", "fire") def fulldesc(self): print "This is a %s wand and it is a %s long" % (self.wandtype, self.length) def addspell(self, spell): self.spells[spell.name] = spell def cast(self, spellname): """Check if requested spell exists, then call its "cast" method if it does.""" if spellname in self.spells: # Check existence by name spell = self.spells[spellname] # Retrieve spell that was added before, name it "spell" spell.cast(self.wandtype) # Call that spell cast method, passing wandtype as argument else: print "This wand doesn't have the %s spell." % spellname print "Available spells:" print "\n".join(sorted(self.spells.keys())) class Spell(object): def __init__(self, name, target): self.name = name self.target = target def cast(self, wandtype=""): print "You cast the spell %s with your %s wand at %s." % ( self.name, wandtype, self.target) if self.name == "lumus": print "The room lights up." elif self.name == "wingardium leviosa": print "You cast the levitation spell.", print "The %s starts to float!" % self.target def __repr__(self): return self.name my_wand = Wand('Phoenix-feather', '12 inches') lumus = Spell('lumus', 'door') wingardium = Spell("wingardium leviosa", "enemy") my_wand.fulldesc() lumus.cast() # Not from a Wand! Ie, we're calling Spell.cast directly print "\n\n" my_wand.addspell(lumus) # Same as my_wand.spells["lumus"] = lumus my_wand.addspell(wingardium) print "\n\n" my_wand.cast("lumus") # Same as my_wand.spells["lumus"].cast(my_wand.wandtype) print "\n\n" my_wand.cast("wingardium leviosa") print "\n\n" my_wand.cast("avada kadavra") # The check in Wand.cast fails, print spell list instead print "\n\n"