2012-05-30 2 views
17

Sto avendo un problema davvero strano con Python super() e ereditarietà e proprietà. Innanzitutto, il codice:Python super e impostazione proprietà parent classe

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

Questo funziona correttamente. Tuttavia, quello che voglio (quello che sembra Pythonic mi)

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

non funziona, anche se

super().x 

ottiene la multa del valore. x in questo caso è una proprietà della superclasse con sia fset che fget definiti. Quindi perché non funziona?

risposta

15

Stavo cercando di trovare il linguaggio corretto per fare il backup del perché questo comportamento è così com'è, in modo da non darti una risposta "perché è solo" ... Ma sembra che questa domanda sia stata posta più di una volta, e che si riduce al comportamento di super(). Puoi vedere una discussione del 2010 su questo comportamento esatto qui: http://mail.python.org/pipermail/python-dev/2010-April/099672.html

In definitiva, si tratta solo delle chiamate super() che ti consentono solo di accedere ai getter direttamente e non ai setter. È necessario accedere ai setter tramite o __set__(). È probabilmente la spiegazione più semplice in quanto "la funzionalità super() non la supporta". Risolverà la funzionalità della proprietà di un'operazione "get", non del setter in un incarico mancino, nell'operazione "set" (da cui la chiamata al metodo). Come puoi vedere dalla data di questo thread di discussione, è ovvio che è stato così dall'introduzione di super().

Forse qualcun altro ha una ragione più specificamente tecnica, ma francamente non sono sicuro che sia importante. Se non è supportato, questo è praticamente un buon motivo.

+6

Ho archiviato un bug: http://bugs.python.org/issue14965 Speriamo che questo sia risolto presto, quindi questa domanda non è più rilevante. – darkfeline

+0

"non è supportato ... un motivo sufficiente" sembra "perché è solo". – simonzack

+0

@simonzack - Ho detto che stavo * cercando * di non dare quel tipo di risposta e di spiegare il più possibile sulla sua funzionalità. – jdi