1

There are two common approaches to calling the parent __init__() from a child:

  1. With an explicit call to the Parent:
class Child(Parent):
    def __init__(self):
        Parent.__init__(self)
  1. With an implicit call to the Parent, using super():
class Child(Parent):
    def __init__(self):
        super().__init__(self)

The second approach has an advantage: if instead of inheriting from Parent, you wanted to inherit from Parent2, you'd simply have to change one line. In the first approach, you'd have to to change two.

My question is as follows: can the same reasoning be applied to decorators?

Consider the following base class:

class Parent:
    def __init__(self, value):
        self._value = value
    
    @property
    def value(self):
        return self._value
    
    @value.setter:
    def value(self, value_new):
        self._value = value_new

If I wanted to override only the getter in a child class, I'd do the following:

class Child(Parent):
    @Parent.value.getter  # Explicit call to the parent class
    def value(self):
        return self._value

Is there a way to avoid explicitly calling the parent? (Just like we did at the top)

The code below doesn't work, but is there something similar that would?

class Child(Parent):
    @super.value.getter   # super instead of explicit call to Parent
    def value(self):
        return self._value
manocormen
  • 747
  • 1
  • 6
  • 17
  • 2
    Maybe you've left out some important detail here, but it looks like you could just use `@property` in the child class - you aren't actually inheriting anything from the parent. – jasonharper Aug 14 '20 at 23:11
  • 1
    @jasonharper I did leave out code for the sake of simplicity. You can imagine that when we override, we would do something to value before returning it. So there's a reason to actually override, not just inherit. – manocormen Aug 14 '20 at 23:28
  • 2
    @FMc I do want to delegate the call to the Parent property getter while at the same time maintaining the inherited setter. If I were to fully override the getter, I'd also need to override the setter. That's why I do it as shown. My question is really about having super as a decorator to avoid explicitly calling the parent. All the rest is incidental. – manocormen Aug 14 '20 at 23:38
  • 1
    @manocormen OK, I'm tracking now -- makes sense. Related, but doesn't really solve the problem, unless you control the Parent class too: https://stackoverflow.com/questions/7019643/overriding-properties-in-python – FMc Aug 15 '20 at 00:28
  • 2
    @manocormen You could set `Child.value` outside the `Child` class definition, by using the builtin `property()` function: roughly `Child.value = property(...)`. That builtin takes params for the various functions: assign `fget` to your custom getter and the rest to the attributes of `Child.__mro__[1].value` -- which is just an indirect way to get `Parent.value`, its property. But that's a lot of work to avoid a tiny code-maintenance hassle. – FMc Aug 15 '20 at 00:37
  • @FMC It is a lot of work. I was really looking for a concise decorator equivalent of super(). It seems that there isn't one in Python, yet. I'll make due with explicit calls to the parent. The workarounds seem to introduce unnecessary complexity. – manocormen Aug 16 '20 at 14:43

0 Answers0