2

I have classes, sharing the same property with the same getters, but different setters. As a simple, useless example, something like:

class Spam():
    @property
    def foo(self):
        return self.bar

    @foo.setter
    def foo(self, foo):
        self.bar = foo


class Eggs(Spam):
    @foo.setter
    def foo(self, foo):
        self.bar = ' '.join(['Egg\'s foo:', foo])

Trying to run this module however throws the following error:

Traceback (most recent call last):
  File "./test.py", line 13, in <module>
    class Eggs(Spam):
  File "./test.py", line 14, in Eggs
    @foo.setter
NameError: name 'foo' is not defined

To make this work as desired, I need to re-define Eggs.foo:

class Eggs(Spam):
    @property
    def foo(self):
        return super().foo

    @foo.setter
    def foo(self, foo):
        self.bar = ' '.join(['Egg\'s foo:', foo])

Is there a way to avoid this re-definition of the property? Since this is very annoying if you have lots of getters and setters like this in several sub-classes like I do.

Richard Neumann
  • 2,986
  • 2
  • 25
  • 50

1 Answers1

8

You need to specify the class name as well:

class Eggs(Spam):
    @Spam.foo.setter
    def foo(self, foo):
        self.bar = ' '.join(['Egg\'s foo:', foo])
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
  • 1
    Just wondering if this can be done without hardcoding the parent class name. – georg Jan 26 '15 at 13:48
  • Indeed, this solves the problem. But I still do not understand why the ```Eggs.foo``` property is not being inherited from the super class. I also second the question of @georg . – Richard Neumann Jan 26 '15 at 15:38
  • 1
    @RichardNeumann You cannot use a plain foo.setter because `foo` doesn't exist while the class properties are created. I will try to post a solution using metaclass(is it's possible) as soon as I get some free time. – Ashwini Chaudhary Jan 26 '15 at 15:42
  • @georg I thought of implementing a custom decorator that hunts down inheritance and does what the hard-coding does... but it may lack precision in some cases, precisely in multiple inheritance. – Hamza Ouaghad Jun 09 '16 at 02:29
  • 1
    If I do this (use @Spam.foo.setter), is it possible to call super().foo setter somehow? I couldn't find a way to do this so far. – zacharmarz Mar 29 '17 at 08:13
  • 2
    @zacharmarz `super(Eggs, type(self)).foo.fset(self, val)` ? – Ashwini Chaudhary Mar 29 '17 at 08:54