Reputation: 6203
I have the following code:
class Desc(object):
@property
def color_desc(self):
return 'Color is ' + self.color
@property
def brand_desc(self):
return 'Brand is ' + self.brand
class Text(Desc):
def __init__(self):
self.color = 'blue'
self.brand = 'volvo'
def main():
t = Text()
print t.color_desc
if __name__ == '__main__':
main()
This correctly works and outputs Color is blue
when run. However, if I modify the code slightly so that the property is set to an actual Class attribute, as in:
class Desc(object):
def __init__(self):
self._color_desc = color_desc
self._brand_desc = brand_desc
@property
def color_desc(self):
return self._color_desc
@color_desc.setter
def color_desc(self):
self._color_desc = 'Color is ' + self.color
@property
def brand_desc(self):
return self._brand_desc
@property
def brand_desc(self):
self._brand_desc = 'Brand is ' + self.brand
class Text(Desc):
def __init__(self):
self.color = 'blue'
self.brand = 'volvo'
All of a sudden, it errs out with AttributeError: 'Text' object has no attribute '_color_desc'
. How come the Text
attributes are inherited correctly in the first place but cannot be accessed in the second one. To me, these two solutions seem to do the same thing.
Upvotes: 0
Views: 118
Reputation: 121944
It's not clear why you thought your second snippet would work at all. It has the following obvious issues:
Desc.__init__
is using two variables (color_desc
and brand_desc
) that aren't actually passed to it - are you expecting them to be in the global scope?brand_desc
.color_desc
setter neither takes nor uses any parameter, so what exactly is it supposed to be setting?Text.__init__
doesn't call or pass anything to the superclass version, or do the job itself.I think what you intended was something like:
class Desc(object):
def __init__(self, color_desc, brand_desc):
self._color_desc = color_desc
self._brand_desc = brand_desc
@property
def color_desc(self):
return 'Color is ' + self._color_desc
@color_desc.setter
def color_desc(self, new_color):
self._color_desc = new_color
@property
def brand_desc(self):
return 'Brand is ' + self._brand_desc
@brand_desc.setter
def brand_desc(self, new_brand):
self._brand_desc = new_brand
class Text(Desc):
def __init__(self):
super(Text, self).__init__('blue', 'volvo')
Although now it looks like Text
should be an instance, not a subclass, of Desc
. You could also simplify by not assigning to e.g. color_desc
at all, using a read-only property:
class Desc(object):
def __init__(self, color, brand):
self.color = color
self.brand = brand
@property
def color_desc(self):
return 'Color is ' + self.color
@property
def brand_desc(self):
return 'Brand is ' + self.brand
car = Desc('blue', 'volvo')
car.color = 'red'
print car.color_desc # Color is red
Now you set the instance's .color
directly, but .color_desc
still gives you the nicely-formatted version.
Upvotes: -1
Reputation: 9102
You need to call the __init__
of the parent class.
Do something like this:
class Text(Desc):
def __init__(self):
self.color = 'blue'
self.brand = 'volvo'
super(Text, self).__init__(0,0)
The init function of your Desc class is incorrectly define. Do this:
class Desc(object):
def __init__(self, color_desc, brand_desc):
self._color_desc = color_desc
self._brand_desc = brand_desc
Upvotes: 3
Reputation: 894
In your Text
class, the __init__
is overriding the Desc.__init__
class, so the _color_desc
attributes is not initialized.
Upvotes: 3