Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overwrite base class attribute with @property of the same name

I am trying to subclass a python class and overwrite a regular attribute with a @property function. The catch is that I can't modify the parent class, and the api for the child class needs to look the same as the parent class (but behave differently). (So my question is different from this one in which the parent class also used a @property method to access the underlying attribute.)

The simplest possible example is

# assume this class can't be overwritten
class Parent(object):
    def __init__(self, a):
        self.attr = a

# how do I make this work?
class Child(Parent):
    def __init__(self, a):
        super(Child, self).__init__(a)

    # overwrite access to attr with a function
    @property
    def attr(self):
        return super(Child, self).attr**2

c = Child(4)
print c.attr # should be 16

This produces an error when the parent init method is called.

<ipython-input-15-356fb0400868> in __init__(self, a)
      2 class Parent(object):
      3     def __init__(self, a):
----> 4         self.attr = a
      5 
      6 # how do I make this work?

AttributeError: can't set attribute

Hopefully it is clear what I want to do and why. But I can't figure out how.

like image 585
Ryan Avatar asked Oct 19 '22 07:10

Ryan


1 Answers

This is easily fixed by adding a setter method

class Child(Parent):
    def __init__(self, a):
        self._attr = None
        super(Child, self).__init__(a)

    # overwrite access to a with a function
    @property
    def attr(self):
        return self._attr**2

    @attr.setter
    def attr(self, value):
        self._attr = value
like image 80
Ryan Avatar answered Oct 23 '22 09:10

Ryan