6

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) 機能させる方法を理解していただければ幸いです。

4

3 に答える 3

8

簡単に言えば、それWand.__init__を継承するクラスでオーバーライドするため、 にCastSpell.wandtype設定されることはありませんCastSpell。その上、 にmy_wand情報を渡すことができないcast_spellため、継承の役割について混乱しています。

どのように行うかに関係なく、何らかの形で渡して に渡す必要がありlengthます。1 つの方法は、それらを に直接含めることです。wandtypeCastSpellCastSpell.__init__

class CastSpell(Wand):
    def __init__(self, spell, thing, length, wandtype):
        self.spell = spell 
        self.thing = thing
        self.length = length
        self.wandtype = wandtype

もう 1 つのより一般的な方法は、これら 2 つを基本クラスの own に渡すこと__init__()です。

class CastSpell(Wand):
    def __init__(self, spell, thing, length, wandtype):
        self.spell = spell 
        self.thing = thing
        super(CastSpell, self).__init__(length, wandtype)

もう 1 つの方法は、 ( aは一種の? または何か aが行うもの? )CastSpellから継承するのをやめ、代わりに各 Wand にいくつかの s を含めることができるようにすることです。 "has-a" (aはs を持っています) を試してください。WandCastSpellWandWandCastSpellCastSpellWandWandSpell

以下は、ワンドに呪文を保存するための単純な方法ですが、それほど優れているわけではありません。

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"
于 2012-05-20T01:21:19.737 に答える
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 はアクションであり、Wand のメソッドのように聞こえます。

class Wand(object):
    [...]
    def cast_spell(self, spell, thing):
         [etc.]
于 2012-05-20T01:20:54.150 に答える
1

ええ、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.

とはいえ、継承権を使用していないようです。ワンドが「モノ」であるのに対し、キャストスペルは「アクション」です。これは、継承にとって適切な抽象化ではありません。

于 2012-05-20T01:23:10.977 に答える