关于SO的类似问题包括:this one和this。我还阅读了我能找到的所有在线文档,但我仍然很困惑。我很感激你的帮助。
我想在CastSpell类lumus方法中使用Wand类.wandtype属性。但我不断收到错误“AttributeError:'CastSpell'对象没有属性'wandtype'。”
此代码有效:
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()
此代码,尝试继承,但没有。
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)如何使它工作。
答案 0 :(得分:6)
简单地说,您在从其继承的类中覆盖Wand.__init__
,因此CastSpell.wandtype
中永远不会设置CastSpell
。除此之外,my_wand
无法将信息传递到cast_spell
,因此您对继承的作用感到困惑。
无论你如何做,你都必须以某种方式将length
和wandtype
传递给CastSpell
。一种方法是将它们直接包含在CastSpell.__init__
中:
class CastSpell(Wand):
def __init__(self, spell, thing, length, wandtype):
self.spell = spell
self.thing = thing
self.length = length
self.wandtype = wandtype
另一种更通用的方法是将这两个传递给基类'自己的__init__()
:
class CastSpell(Wand):
def __init__(self, spell, thing, length, wandtype):
self.spell = spell
self.thing = thing
super(CastSpell, self).__init__(length, wandtype)
另一种方法是停止CastSpell
Wand
继承CastSpell
某种Wand
?或某种Wand
继承?)相反,让每个魔杖都能有一些CastSpell
:而不是“is-a”(CastSpell
是一种Wand
),请尝试“has-a”( Wand
有Spell
s。。
这是一个简单的,不太好的方法来使用魔杖存储法术:
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 "\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! I.e., 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"
答案 1 :(得分:1)
您需要调用超类的init方法。否则,永远不会在当前的CastSpell实例上设置wandtype和length。
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
或者,您可以在init方法之外的对象上添加wandtype和length作为属性:
class Wand(object):
wandtype = None
length = None
然后,它们将始终可用(尽管它们的值将为None,直到它们被初始化)。
但是,你确定CastSpell应该是Wand的子类吗? CastSpell是一个动作,听起来更像它应该是魔杖的方法。
class Wand(object):
[...]
def cast_spell(self, spell, thing):
[etc.]
答案 2 :(得分:0)
是的,super()
不是你想要的。有关原因,请参阅this article。
不幸的是,通过引用超类来显式调用Python中的超类。
如果我正确解释您的问题,您会想知道为什么.length
和.wandtype
属性未显示在CastSpell
的实例中。这是因为没有调用Wand。 init ()方法。你应该这样做:
class CastSpell(Wand):
def __init__(self, spell, thing):
Wand.__init__(self, whateverdefaultvalue_youwantforwandtype, default_value_for_length)
self.spell = spell
etc.
那就是说,你好像没有使用继承权。 CastSpell是一个“动作”,而魔杖是一个“事物”。这实际上并不是一种对继承有意义的抽象。