Python类继承AttributeError的 - 为什么? 怎么修?(Python Clas

2019-07-29 11:24发布

在如此相似的问题包括: 这个和这个 。 我还通过所有的在线文档可以找我看,但我仍然很困惑。 我会是你的帮助表示感谢。

我想用法杖类.wandtype属性在我CastSpell类Lumus公司的方法。 不过,我不断收到错误“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() 

我一直在使用超()方法无济于事尝试。 我真的明白为什么类继承不是在这种情况下工作的帮助理解A),B)如何得到它的工作。

Answer 1:

简单地说,你重写Wand.__init__中,从它继承的类,所以CastSpell.wandtype从未在设定CastSpell 。 除此之外, my_wand无法传递信息到cast_spell ,让你感到困惑传承的作用。

不管你怎么做,你必须以某种方式传递lengthwandtypeCastSpell 。 一种方法是直接包含他们进入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 ,它出现:而不是“是一个”(一CastSpell是一种Wand ),尝试“有-A”(一Wand具有Spell或多个)。

这里有一个魔杖店法术简单,没有那么伟大的方式:

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"


Answer 2:

是啊, super()是不是你想要的。 请参阅本文的详细信息,何乐而不为。

在Python超正常通话(不幸)参照超做了明确。

如果我解释你的问题吧,你想知道为什么.length.wandtype属性不显示的情况下,高达CastSpell 。 这是因为魔杖。 init()方法不被调用。 你应该做的是这样的:

class CastSpell(Wand):
    def __init__(self, spell, thing):
        Wand.__init__(self, whateverdefaultvalue_youwantforwandtype, default_value_for_length)
        self.spell = spell
        etc.

这就是说,你似乎没有使用权的继承是。 CastSpell是一个“行动”,而棒是一个“东西”。 这是不是一个真正的抽象,它是有道理的继承。



Answer 3:

您需要调用父类的init方法。 否则,wandtype和长度永远不会对当前CastSpell实例设置。

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和长度init方法以外的对象属性:

class Wand(object):
    wandtype = None
    length = None

然后,他们将永远是可用的(虽然直到他们已经被初始化它们会没有值)。


但是,你确定CastSpell应该是棒的一个子类? CastSpell是一个动作,这听起来更像它应该是棒的方法。

class Wand(object):
    [...]
    def cast_spell(self, spell, thing):
         [etc.]


文章来源: Python Class Inheritance AttributeError - why? how to fix?