Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python overriding getter without setter

class human(object):     def __init__(self, name=''):         self.name = name      @property     def name(self):         return self._name      @name.setter     def name(self, value):         self._name = value  class superhuman(human):     @property     def name(self):         return 'super ' + name  s = superhuman('john') print s.name  # Doesn't work :( "AttributeError: can't set attribute" s.name = 'jack' print s.name 

I want to be able to override the property but be able to use the super parent's setter without having to override the setter in the child class.

Is that pythonicaly possible?

like image 869
LuRsT Avatar asked Apr 03 '13 11:04

LuRsT


People also ask

Do you need getters and setters in Python?

You don't need any getters, setters methods to access or change the attributes. You can access it directly using the name of the attributes.

What is@ getter?

Getters and setters are used to protect your data, particularly when creating classes. For each instance variable, a getter method returns its value while a setter method sets or updates its value. Given this, getters and setters are also known as accessors and mutators, respectively.

What is@ getter annotation?

The @Getter annotation is used to generate the default getter implementation for fields that are annotated with the annotation. This annotation can also be used at the class level in which Lombok will generate the getter methods for all fields. The default implementation is to return the field as it is.

What is the difference between constructor and getter setter?

The constructors are used to initialize the instance variable of a class or, create objects. The setter/getter methods are used to assign/change and retrieve values of the instance variables of a class.


1 Answers

Use just the .getter decorator of the original property:

class superhuman(human):     @human.name.getter     def name(self):         return 'super ' + self._name 

Note that you have to use the full name to reach the original property descriptor on the parent class.

Demonstration:

>>> class superhuman(human): ...     @human.name.getter ...     def name(self): ...         return 'super ' + self._name ...  >>> s = superhuman('john') >>> print s.name super john >>> s.name = 'jack' >>> print s.name super jack 

The property descriptor object is just one object, even though it can have multiple methods associated with it (the getter, setter and deleter). The .getter, .setter and .deleter decorator functions provided by an existing property descriptor return a copy of the descriptor itself, with that one specific method replaced.

So in your human base class what happens is that you first create the descriptor with the @property decorator, then replace that descriptor with one that has both a getter and a setter with the @name.setter syntax. That works because python decorators replace the original decorated function with the same name, it basically executes name = name.setter(name). See How does the @property decorator work? for the details on how that all works.

In your subclass you simply use that trick to create a new copy of the descriptor with just the getter replaced.

like image 76
Martijn Pieters Avatar answered Sep 28 '22 16:09

Martijn Pieters