Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding inherited properties’ getters and setters in Python

I’m currently using the @property decorator to achieve “getters and setters” in a couple of my classes. I wish to be able to inherit these @property methods in a child class.

I have some Python code (specifically, I’m working in py3k) which looks vaguely like so:

class A:     @property     def attr(self):         try:             return self._attr         except AttributeError:             return ''  class B(A):     @property     def attr(self):         return A.attr   # The bit that doesn't work.      @attr.setter     def attr(self, value):         self._attr = value  if __name__ == '__main__':     b = B()     print('Before set:', repr(b.attr))     b.attr = 'abc'     print(' After set:', repr(b.attr)) 

I have marked the part that doesn’t work with a comment. I want the base class’ attr getter to be returned. A.attr returns a property object (which is probably very close to what I need!).

Edit:
After receiving the answer below from Ned I thought up what I think is a more elegant solution to this problem.

class A:     @property     def attr(self):         try:             return self._attr         except AttributeError:             return ''  class B(A):             @A.attr.setter     def attr(self, value):         self._attr = value  if __name__ == '__main__':     b = B()     print('Before set:', repr(b.attr))     b.attr = 'abc'     print(' After set:', repr(b.attr)) 

The .setter decorator expects a property object which we can get using @A.attr. This means we do not have to declare the property again in the child class.

(This is the difference between working on a problem at the end of the day vs working on it at the beginning of the day!)

like image 849
casr Avatar asked Jul 26 '10 16:07

casr


People also ask

Are getters and setters inherited?

They don't inherit private variables. This is simply not accurate. Both methods and variables (fields) have visibility restrictions. The subclass can always access (see) protected and public and may (if in same package) access default scoped.

Are properties inherited Python?

Inheritance allows us to define a class that inherits all the methods and properties from another class. Parent class is the class being inherited from, also called base class. Child class is the class that inherits from another class, also called derived class.

What is the pythonic way to write getters and setters in python?

(Each decorator usage copies and updates the prior property object, so note that you should use the same name for each set, get, and delete function/method.) You should avoid this: def set_property(property,value): def get_property(property):


2 Answers

To override a setter in python 2 I did this:

class A(object):     def __init__(self):         self._attr = None      @property     def attr(self):         return self._attr      @attr.setter     def attr(self, value):         self._attr = value   class B(A):     @A.attr.setter     def attr(self, value):         # Do some crazy stuff with `value`         value = value[0:3]         A.attr.fset(self, value) 

To understand where A.attr.fset came from see the documentation on the property class: https://docs.python.org/2/library/functions.html#property

like image 197
jmagnusson Avatar answered Sep 25 '22 17:09

jmagnusson


I think you want:

class B(A):     @property     def attr(self):         return super(B, self).attr 

You mention wanting to return the parent class's getter, but you need to invoke the getter, not return it.

like image 44
Ned Batchelder Avatar answered Sep 22 '22 17:09

Ned Batchelder