Python Class Inheritance AttributeError - why? how to fix?

2024/9/25 20:23:41

Similar questions on SO include: this one and this. I've also read through all the online documentation I can find, but I'm still quite confused. I'd be grateful for your help.

I want to use the Wand class .wandtype attribute in my CastSpell class lumus method. But I keep getting the error "AttributeError: 'CastSpell' object has no attribute 'wandtype'."

This code works:

class Wand(object):def __init__(self, wandtype, length):self.length = length self.wandtype = wandtypedef 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 = thingdef 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() 

This code, with attempted inheritance, doesn't.

class Wand(object):def __init__(self, wandtype, length):self.length = length self.wandtype = wandtypedef 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 = thingdef 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() 

I've tried using the super() method to no avail. I'd really appreciate your help understanding a) why class inheritance isn't working in this case, b) how to get it to work.

Answer

To put it simply, you override Wand.__init__ in the class that inherits from it, so CastSpell.wandtype is never set in CastSpell. Besides that, my_wand can't pass information into cast_spell, so you're confused about the role of inheritance.

Regardless of how you do it, you have to somehow pass length and wandtype to CastSpell. One way would be to include them directly into CastSpell.__init__:

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

Another, more generic way would be to pass these two to the base class' own __init__():

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

Another way would be to stop making CastSpell inherit from Wand (is CastSpell a kind of Wand? or something a Wand does?) and instead make each Wand be able to have some CastSpells in it: instead of "is-a" (a CastSpell is a kind of Wand), try "has-a" (a Wand has Spells).

Here's a simple, not so great way to have a Wand store spells:

class Wand(object):def __init__(self, wandtype, length):self.length = lengthself.wandtype = wandtypeself.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] = spelldef cast(self, spellname):"""Check if requested spell exists, then call its "cast" method if it does."""if spellname in self.spells: # Check existence by namespell = 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 argumentelse:print "This wand doesn't have the %s spell." % spellnameprint "Available spells:"print "\n".join(sorted(self.spells.keys()))class Spell(object):def __init__(self, name, target):self.name = nameself.target = targetdef 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.targetdef __repr__(self):return self.namemy_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"
https://en.xdnf.cn/q/71537.html

Related Q&A

Is it possible to display pandas styles in the IPython console?

Is it possible to display pandas styles in an iPython console? The following code in a Jupyter notebookimport pandas as pd import numpy as npnp.random.seed(24) df = pd.DataFrame({A: np.linspace(1, 10,…

HEAD method not allowed after upgrading to django-rest-framework 3.5.3

We are upgrading django-rest-framework from 3.1.3 to 3.5.3. After the upgrade all of our ModelViewSet and viewsets.GenericViewSet views that utilize DefaultRouter to generate the urls no longer allow …

How do I specify server options?

Im trying to run gRPC server in Python. I found a way to do it like this:import grpc from concurrent import futuresserver = grpc.server(futures.ThreadPoolExecutor(max_workers=100)) ... # add my grpc se…

How to find collocations in text, python

How do you find collocations in text? A collocation is a sequence of words that occurs together unusually often. python has built-in func bigrams that returns word pairs. >>> bigrams([more, i…

How to set size of a Gtk Image in Python

How can I set the width and height of a GTK Image in Python 3.

Numpy Vectorized Function Over Successive 2d Slices

I have a 3D numpy array. I would like to form a new 3d array by executing a function on successive 2d slices along an axis, and stacking the resulting slices together. Clearly there are many ways to do…

MySQL and Python Select Statement Issues

Thanks for taking the time to read this. Its going to be a long post to explain the problem. I havent been able to find an answer in all the usual sources.Problem: I am having an issue with using the …

How to pass variable in url to Django List View

I have a Django generic List View that I want to filter based on the value entered into the URL. For example, when someone enters mysite.com/defaults/41 I want the view to filter all of the values mat…

Django Select Option selected issue

I tried to follow some examples on stackoverflow for option selected in select list but still, I could not get it work.This is my code snippet<select name="topic_id" style="width:90%&…

reading tab-delimited data without header in pandas

Im having trouble using pandas to open tab-delimited data without headers.My test data (actually contains 200 lines, of which I am showing the first 10):Tag19184 CTAAC hffef 1 a 36 - chr1…