Python Class Inheritance AttributeError - why? how to fix?
类似的问题包括:这个和这个。我也通读了所有我能找到的在线文档,但我还是很困惑。我很感激你的帮助。
我想在castspell类lumus方法中使用wand类.wandtype属性。但我不断地得到错误"attributeError:'castspell'对象没有属性'wandtype'。
此代码有效:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class Wand(object): def __init__(self, wandtype, length): self.length = length self.wandtype = wandtype def fulldesc(self): print"This is a %s wand and it is a %s long" % (self.wandtype, self.length) class CastSpell(object): def __init__(self, spell, thing): self.spell = spell self.thing = thing def lumus(self): print"You cast the spell %s with your wand at %s" %(self.spell, self.thing) def wingardium_leviosa(self): print"You cast the levitation spell." my_wand = Wand('Phoenix-feather', '12 inches') cast_spell = CastSpell('lumus', 'door') my_wand.fulldesc() cast_spell.lumus() |
尝试继承的代码没有。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class Wand(object): def __init__(self, wandtype, length): self.length = length self.wandtype = wandtype def fulldesc(self): print"This is a %s wand and it is a %s long" % (self.wandtype, self.length) class CastSpell(Wand): def __init__(self, spell, thing): self.spell = spell self.thing = thing def lumus(self): print"You cast the spell %s with your %s wand at %s" %(self.spell, self.wandtype, self.thing) #This line causes the AttributeError! print"The room lights up." def wingardium_leviosa(self): print"You cast the levitation spell." my_wand = Wand('Phoenix-feather', '12 inches') cast_spell = CastSpell('lumus', 'door') my_wand.fulldesc() cast_spell.lumus() |
号
我尝试过使用super()方法,但没有用。我非常感谢您的帮助,理解a)为什么类继承在这种情况下不起作用,b)如何使它起作用。
简单地说,在继承它的类中重写
不管你怎么做,你都必须以某种方式把
1 2 3 4 5 6 | class CastSpell(Wand): def __init__(self, spell, thing, length, wandtype): self.spell = spell self.thing = thing self.length = length self.wandtype = wandtype |
。
另一种更通用的方法是将这两种方法传递给基类自己的
1 2 3 4 5 | class CastSpell(Wand): def __init__(self, spell, thing, length, wandtype): self.spell = spell self.thing = thing super(CastSpell, self).__init__(length, wandtype) |
另一种方法是停止使
下面是一个简单的,不是很好的魔杖店法术方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | 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's cast method, passing wandtype as argument else: print"This wand doesn't have the %s spell." % spellname print"Available spells:" print" ".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! I.e., we're calling Spell.cast directly print" " my_wand.addspell(lumus) # Same as my_wand.spells["lumus"] = lumus my_wand.addspell(wingardium) print" " my_wand.cast("lumus") # Same as my_wand.spells["lumus"].cast(my_wand.wandtype) print" " my_wand.cast("wingardium leviosa") print" " my_wand.cast("avada kadavra") # The check in Wand.cast fails, print spell list instead print" " |
。
您需要调用超类的init方法。否则,不会在当前castspell实例上设置wandtype和length。
1 2 3 4 5 | class CastSpell(Wand): def __init__(self, spell, thing): super(CastSpell, self).__init__(A, B) # A, B are your values for wandtype and length self.spell = spell self.thing = thing |
或者,可以将wandtype和length作为属性添加到init方法之外的对象上:
1 2 3 | class Wand(object): wandtype = None length = None |
号
然后,它们将始终可用(尽管在初始化之前它们的值将为"无")。
但是,你确定施法应该是魔杖的一个子类吗?施法是一种动作,听起来更像是一种魔杖的方法。
1 2 3 4 | class Wand(object): [...] def cast_spell(self, spell, thing): [etc.] |
是的,江户记1〔20〕不是你想要的。请参阅本文了解为什么不这样做的详细信息。
在python中对超类的正常调用(不幸的是)是通过引用超类显式地完成的。
如果我正确地解释了你的问题,你会奇怪为什么
1 2 3 4 5 | class CastSpell(Wand): def __init__(self, spell, thing): Wand.__init__(self, whateverdefaultvalue_youwantforwandtype, default_value_for_length) self.spell = spell etc. |
。
也就是说,你似乎没有使用继承权。施法是一种"行动",而魔杖是一种"东西"。这并不是一个对继承很有意义的抽象。