optional argument to a subclass of a class

Peter Otten __peter__ at web.de
Fri May 21 04:07:47 EDT 2010


Alex Hall wrote:

> Hi all,
> I am now trying to allow my classes, all of which subclass a single
> class (if that is the term), to provide optional arguments. Here is
> some of my code:
> 
> class Craft():
>  def __init__(self,
>  name,
>  isAircraft=False,
>  id=helpers.id(),
>  hits=0,
>  weapons=[]):
>   self.name=name
>   self.id=id
>   self.hits=hits
>   self.weapons=weapons
>   self.isAircraft=isAircraft
>  #end def
> #end class
> 
> 
> #now a class for each type of craft in the game
> #each will subclass the Craft class, but each also has its own settings
> 
> class Battleship(Craft):
>  def __init__(self,
>  name,
>  maxHits):
>   Craft.__init__(self, name)
>   self.maxHits=maxHits
>   self.length=maxHits #in Battleship, each ship's length is the same
> as how many times it can be hit
>  #end def
> #end class
> 
> 
> I want to be able to say something like
> b=Battleship("battleship1", 4, weapons=["missile1","missile2"])
> When I do that, though, I get a traceback on the above line saying
> "type error: __init__() got an unexpected keyword argument 'weapons'".
> What did I do wrong / what do I need to change so that any Craft
> (Battleship, Carrier, and so on) can optionally provide a list of
> weapons, or any other arguments to which I assign default values in my
> Craft class? I hope this makes sense.

You have to repeat the arguments for the base class in the Battleship 
initializer. Battleship(...) will only invoke Battleship.__init__(...), not 
Craft.__init__(...) -- so you have to do that explicitly inside 
Battleship.__init__() while passing along all parameters it is supposed to 
process. As simplified example:

class Craft(object):
    def __init__(self, name, id=None, weapons=None):
        if id is None: 
            id = helpers.id()
        if weapons is None:
            weapons = []
        self.name = name
        self.id = id
        self.weapons = weapons

class Battleship(Craft):
    def __init__(self, name, id=None, weapons=None, max_hits=None):
        Craft.__init__(self, name, id, weapons)
        self.max_hits = max_hits

Notice how using None to signal that a value was not provided simplifies 
things; without it you'd have to put a meanigful default for weapons into 
both the Craft and Battleship class. If you want a unique id for every Craft 
providing helpers.id() as a default is just wrong; default arguments are 
calculated once and you would end up with the same id for every Craft 
instance.

Peter




More information about the Python-list mailing list