Python超级和设置父类属性

时间:2012-05-30 05:19:31

标签: python super

我对Python super()以及继承和属性有一个非常奇怪的问题。首先,代码:

#!/usr/bin/env python3

import pyglet
import pygame

class Sprite(pyglet.sprite.Sprite):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.rect = pygame.Rect(0, 0, self.width, self.height)
        self.rect.center = self.x, self.y

    @property
    def x(self):
        return super().x

    @x.setter
    def x(self, value):
        super(Sprite, self.__class__).x.fset(self, value)
        self.rect.centerx = value

    @property
    def y(self):
        return super().y

    @y.setter
    def y(self, value):
        super(Sprite, self.__class__).y.fset(self, value)
        self.rect.centery = value

这很好用。但是,我想要的东西(对我来说似乎是Pythonic)

#super(Sprite, self.__class__).x.fset(self, value)
super().x = value
即使

也不起作用

super().x

获得价值。在这种情况下,x是超类的属性,同时定义了fset和fget。那为什么不起作用?

2 个答案:

答案 0 :(得分:17)

我试图找到正确的语言来支持为什么这种行为是这样的,以免给你一个“因为它只是”答案......但似乎这个问题已经被问到了曾经,它归结为super()的行为。您可以在此处查看关于此确切行为的2010年讨论:http://mail.python.org/pipermail/python-dev/2010-April/099672.html

最终,它确实只是让super()调用只让你直接访问getter而不是setter。必须通过fset()__set__()访问制定者。最简单的解释是“超级()功能只是不支持它”。它将在“set”操作中解析“get”操作的属性功能,而不是左手赋值中的setter(因此fset()方法调用)。从这个讨论主题的日期可以看出,自super()引入以来,它显然就是这样。

也许其他人有更具体的技术原因,但坦率地说,我不确定它是否重要。如果它不受支持,那就足够了。

答案 1 :(得分:0)

super(type(self), type(self)).setter.fset(self, value) 是一种常见的解决方法,但是它不适用于多重继承,这可能会改变 mro。

试试我的解决方案 duper(链接如下):duper(super()).setter = value

https://gist.github.com/willrazen/bef3fcb26a83dffb6692e5e10d3e67ac