简体   繁体   English

Python super 和设置父类属性

[英]Python super and setting parent class property

I'm having a really strange problem with Python super() and inheritance and properties.我在 Python super() 以及继承和属性方面遇到了一个非常奇怪的问题。 First, the code:首先,代码:

#!/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

This works fine.这工作正常。 However, what I want (what seems Pythonic to me)然而,我想要的(对我来说似乎是 Pythonic 的)

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

doesn't work even though即使不起作用

super().x

gets the value fine.得到很好的价值。 x in this case is a property of the superclass with both fset and fget defined.在这种情况下,x 是定义了 fset 和 fget 的超类的属性。 So why doesn't it work?那为什么不起作用呢?

I was trying to find the correct language to back up why this behavior is the way it is, so as not to give you a "because it just is" answer... But it seems this question has been asked more than once, and that it boils down to the behavior of super() .我试图找到正确的语言来支持为什么这种行为是这样的,以免给你一个“因为它就是”的答案......但似乎这个问题已经被问过不止一次了,而且它归结为super()的行为。 You can see a 2010 discussion about this exact behavior here: http://mail.python.org/pipermail/python-dev/2010-April/099672.html您可以在此处查看 2010 年有关此确切行为的讨论: http : //mail.python.org/pipermail/python-dev/2010-April/099672.html

Ultimately, it really does just come down to super() calls only letting you access getters directly, and not setters.最终,它确实归结为 super() 调用,只允许您直接访问 getter,而不是 setter。 Setters must be accessed via fset() or __set__() . Setter 必须通过fset()__set__() It is probably easiest explained as "super() functionality just doesn't support it".最简单的解释可能是“super() 功能不支持它”。 It will resolve the property functionality of a "get" operation, not the setter in a left handed assignment, in the "set" operation (hence the fset() method call).它将在“set”操作(因此调用fset()方法)中解析“get”操作的属性功能,而不是左手赋值中的 setter。 As you can see from the date of this discussion thread, its obviously been this way since the introduction of super() .正如您从本讨论线程的日期中看到的那样,自super()引入以来,显然就是这种方式。

Maybe someone else has a more specifically technical reason, but frankly I'm not sure it even matters.也许其他人有更具体的技术原因,但坦率地说,我不确定这是否重要。 If its not supported, thats pretty much a good enough reason.如果它不支持,那几乎是一个足够好的理由。

super(type(self), type(self)).setter.fset(self, value) is a common workaround, however it doesn't work adequately with multiple inheritance, which can change mro. super(type(self), type(self)).setter.fset(self, value)是一种常见的解决方法,但是它不能很好地处理多重继承,这可能会改变 mro。

Try my solution duper (link below): duper(super()).setter = value试试我的解决方案 duper(下面的链接): duper(super()).setter = value

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM