Overriding an Inherited Property

I have a class called Node that has an importance and getter installer, below:

 class Node: @property def importance(self): return self._importance @importance.setter def importance(self, new_importance): if new_importance is not None: new_importance = check_type_and_clean(new_importance, int) assert new_importance >= 1 and new_importance <= 10 self._importance = new_importance 

Subsequently, I have a Theorem class that inherits from Node . The only difference between Theorem and a Node , in terms of importance , is that a Theorem must have an importance at least 3 .

How can a theorem inherit the importance installer, but add an additional constraint that importance >= 3 ?

I tried to do it as follows:

 class Theorem(Node): @importance.setter def importance(self, new_importance): self.importance = new_importance # hoping this would use the super() setter assert self.importance >= 3 
+8
python inheritance oop
source share
3 answers

You can reference an existing property directly through the Node class and use the setter property method to create a new property:

 class Theorem(Node): @Node.importance.setter def importance(self, new_importance): # You can change the order of these two lines: assert new_importance >= 3 Node.importance.fset(self, new_importance) 

This will create a new property in the Theorem class that uses the getter method from Node.importance , but replaces the setter method with another. That the properties as a whole work: calling the setter property returns a new property using a custom setter, which usually just replaces the old property.

You can learn more about how properties work by reading this answer (and the question too).

+6
source share

One way to do this is to implement a new property on Theorem using getter Node by providing a new setter method and the calling Node box explicitly inside it:

 class Theorem(Node): def _set_importance(self, new): Node.importance.fset(self, new) assert self.importance >= 3 importance = property(Node.importance.fget, _set_importance) 

As far as I know, this cannot be done with super .


In this error report , you can do:

 class Theorem(Node): def _set_importance(self, new): super(Theorem, Theorem).importance.fset(self, new) assert self.importance >= 3 importance = property(Node.importance.fget, _set_importance) 

However, this is clearly a bit uncomfortable; a patch to allow super() instead seems to be planned for Python 3.5 (due to September 2015 ).

+3
source share

Here is a completely different solution for a broader problem, with much less falsification:

 class Node: MIN_IMPORTANCE = 1 MAX_IMPORTANCE = 10 @property def importance(self): return self._importance @importance.setter def importance(self, new_importance): if new_importance is not None: new_importance = check_type_and_clean(new_importance, int) assert (new_importance >= self.MIN_IMPORTANCE and new_importance <= self.MAX_IMPORTANCE) self._importance = new_importance class Theorem(Node): MIN_IMPORTANCE = 3 # and that all it takes! 

In my opinion, this is expressed:

The only difference between a Theorem and a Node is how importance that a Theorem must have an importance at least 3 .

much more clearly than overriding a property setting tool.


Note that assert usually used for testing and debugging, and not as part of the overall program flow, and, of course, not for the things you expect; see for example Best Practices for Python Assert .

+1
source share

All Articles