问题
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