Calling the setter of a super class in a mixin

房东的猫 提交于 2020-01-17 05:14:28

问题


Suppose I have the following (not quite biologically correct) classes:

class AnimalBaseClass:
    def __init__(self):
        self._limbs = None

    @property
    def limbs(self):
        return self._limbs

    @limbs.setter
    def limbs(self, value):
        self.paws = value
        self._limbs = value


class BipedalMixIn:
    @property
    def limbs(self):
        return super().limbs

    @limbs.setter
    def limbs(self, value):
        self.bipedal = (value == 2)
        # does not work
        super().limbs = value

Here super().limbs = value is not supported by python. If BipedalMixIn was not a mixin, I could use the super class's name directly, but is there any simple alternative, to call the super class's setter in a mixin?


回答1:


The following works, although any simpler answers are appreciated.

class AnimalBaseClass:
    def __init__(self):
        self._limbs = None

    @property
    def limbs(self):
        return self._limbs

    @limbs.setter
    def limbs(self, value):
        self.paws = value
        self._limbs = value


class BipedalMixIn:
    @property
    def limbs(self):
        return super().limbs

    @limbs.setter
    def limbs(self, value):
        self.bipedal = (value == 2)
        # works!
        super(BipedalMixIn, self.__class__).limbs.__set__(self, value)


class Bird(BipedalMixIn, AnimalBaseClass):
    pass


bird = Bird()
bird.limbs = 2
print(bird.bipedal)    # True
print(bird.paws)        # 2



回答2:


Firstly, if you're working under Python 2.x, make sure all of your classes directly or indirectly inherit from object. Otherwise, @property does not work at all.

To steal the example code from this comment in OP's linked bug:

super(BipedalMixin, BipedalMixin).limbs.__set__(self, value)

Let's break this apart:

super(BipedalMixin, BipedalMixin)

Normally, we pass an instance as the first argument. Here, we're instead passing a class, to look up class attributes specifically and disable any descriptor magic.

.limbs.__set__(self, value)

This invokes the property's __set__() method, which calls the setter. It is normally invoked automatically by the foo.limbs = bar syntax.



来源:https://stackoverflow.com/questions/27664632/calling-the-setter-of-a-super-class-in-a-mixin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!