I have two classes, Field
and Background
. They look a little bit like this:
class Field( object ):
def __init__( self, a, b ):
self.a = a
self.b = b
self.field = self.buildField()
def buildField( self ):
field = [0,0,0]
return field
class Background( Field ):
def __init__( self, a, b, c ):
super(Background, self).__init__( a, b )
self.field = self.buildField( c )
def buildField( self, c ):
field = [c]
return field
a, b, c = 0, 1, 2
background = Background( a, b, c )
This error is pointing to Field's buildField()
:
"TypeError: buildField() takes exactly 2 arguments (1 given)."
I expected Background init() to be called first. To pass "a, b" to Fields init(), Field to assign a and b then to assign a list with three 0's in it to field. Then for Background's init() to continue, to then call its own buildField() and override self.field with a list containing c.
It seems I don't fully understand super(), however i was unable to find a solution to my issue after looking at similar inheritance problems on the web and around here.
I expected behavior like c++ where a class can override a method that was inherited. How can i achieve this or something similar.
Most issues I found related to this were people using double underscores. My experience with inheritance with super is using the inherited class init() to just pass different variables to the super class. Nothing involving overwriting anything.
I expected Background init() to be called. To pass "a, b" to Fields init(), Field to assign a and b
So far, so good.
then to assign a list with three 0's in it to field.
Ah. This is where we get the error.
self.field = self.buildField()
Even though this line occurs within Field.__init__
, self
is an instance of Background
. so self.buildField
finds Background
's buildField
method, not Field
's.
Since Background.buildField
expects 2 arguments instead of 1,
self.field = self.buildField()
raises an error.
So how do we tell Python to call Field
's buildField
method instead of Background
's?
The purpose of name mangling (naming an attribute with double underscores) is to solve this exact problem.
class Field(object):
def __init__(self, a, b):
self.a = a
self.b = b
self.field = self.__buildField()
def __buildField(self):
field = [0,0,0]
return field
class Background(Field):
def __init__(self, a, b, c):
super(Background, self).__init__(a, b)
self.field = self.__buildField(c)
def __buildField(self, c):
field = [c]
return field
a, b, c = 0, 1, 2
background = Background(a, b, c)
The method name __buildField
is "mangled" to _Field__buildField
inside Field
so inside Field.__init__
,
self.field = self.__buildField()
calls self._Field__buildField()
, which is Field
's __buildField
method. While similarly,
self.field = self.__buildField(c)
inside Background.__init__
calls Background
's __buildField
method.