views:

846

answers:

4

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
+3  A: 

Super should do the trick:

return super().bar
Pankrat
TypeError: super() takes at least 1 argument (0 given)
Aaron Maenpaa
super( MyClass, self ).bar()
S.Lott
I guess (well, judging by the link :P), this answer is python3-related. In python3 super() can take zero arguments, yes.
shylent
super() works without arguments in Python 3 and is equivalent to super(MyClass, self) but more readable in my book.
Pankrat
+2  A: 

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
workmad3
+6  A: 

You want to call the base class function which is called by property:

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar(self)

This is the most obvious thing to try I think - but it does not work because bar is a property, not a callable. But a property is just an object, with a getter method to find the correponding attribute:

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar.fget(self)
David Cournapeau
+1... and Foo.bar.fset(self, c) for the setter
Jarret Hardie
Thank you!!....
Matt Joiner
A: 
    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)

shylent