How to call a property of the base class if this property is being overwritten in the derived class?

Question!

I'm changing some classes of mine from an extensive use of getters and setters to a more pythonic use of properties.

But now I'm stuck because some of my previous getters or setters would call the corresponding method of the base class, and then perform something else. But how can this be accomplished with properties? How to call the property getter or setter from the base class?

Of course just calling the attribute itself gives infinite recursion.

class Foo(object):

    @property
    def bar(self):
    	return 5

    @bar.setter
    def bar(self, a):
    	print a

class FooBar(Foo):

    @property
    def bar(self):
    	# return the same value
    	# as in the base class
    	return self.bar # --> recursion!

    @bar.setter
    def bar(self, c):
    	# perform the same action
    	# as in the base class
    	self.bar = c    # --> recursion!
    	# then do something else
    	print 'something else'

fb = FooBar()
fb.bar = 7
By : UncleZeiv


Answers
    class Base(object):
      def method(self):
        print "Base method was called"

    class Derived(Base):
      def method(self):
        super(Derived,self).method()
        print "Derived method was called"

    d = Derived()
    d.method()

(that is unless I am missing something from your explanation)

By : shylent


try

@property
def bar:
    return super(FooBar, self).bar

Although I'm not sure if python supports calling the base class property. A property is actually a callable object which is set up with the function specified and then replaces that name in the class. This could easily mean that there is no super function available.

You could always switch your syntax to use the property() function though:

class Foo(object):

    def _getbar(self):
        return 5

    def _setbar(self, a):
        print a

    bar = property(_getbar, _setbar)

class FooBar(Foo):

    def _getbar(self):
        # return the same value
        # as in the base class
        return super(FooBar, self)._getbar()

    def bar(self, c):
        super(FooBar, self)._setbar(c)
        print "Something else"

    bar = property(_getbar, _setbar)

fb = FooBar()
fb.bar = 7
By : workmad3


There is an alternative using super that does not require to explicitly reference the base class name.

Base class A:

class A(object):
    def __init__(self):
        self._prop = None

    @property
    def prop(self):
        return self._prop

    @prop.setter
    def prop(self, value):
        self._prop = value

class B(A):
    # we want to extend prop here
    pass

In B, accessing the property getter of the parent class A:

As others have already answered, it's:

super(B, self).prop

Or in Python 3:

super().prop

This returns the value returned by the getter of the property, not the getter itself but it's sufficient to extend the getter.

In B, accessing the property setter of the parent class A:

The best recommendation I've seen so far is the following:

A.prop.fset(self, value)

I believe this one is better:

super(B, self.__class__).prop.fset(self, value)

In this example both options are equivalent but using super has the advantage of being independent from the base classes of B. If B were to inherit from a C class also extending the property, you would not have to update B's code.

Full code of B extending A's property:

class B(A):
    @property
    def prop(self):
        value = super(B, self).prop
        # do something with / modify value here
        return value

    @prop.setter
    def prop(self, value):
        # do something with / modify value here
        return super(B, self.__class__).prop.fset(self, value)

One caveat:

Unless your property doesn't have a setter, you have to define both the setter and the getter in B even if you only change the behaviour of one of them.

By : Maxime R.


This video can help you solving your question :)
By: admin