2010-07-26 8 views
21

Actualmente estoy usando el decorador @property para lograr ‘captadores y definidores’ en un par de mis clases. Deseo poder heredar estos métodos @property en una clase secundaria.preponderantes con heredaron captadores y definidores propiedades en Python

que tienen algo de código Python (en concreto, estoy trabajando en py3k) que se parece vagamente a modo:

class A: 
    @property 
    def attr(self): 
     try: 
      return self._attr 
     except AttributeError: 
      return '' 

class B(A): 
    @property 
    def attr(self): 
     return A.attr # The bit that doesn't work. 

    @attr.setter 
    def attr(self, value): 
     self._attr = value 

if __name__ == '__main__': 
    b = B() 
    print('Before set:', repr(b.attr)) 
    b.attr = 'abc' 
    print(' After set:', repr(b.attr)) 

He marcado la parte que no funciona con un comentario. Quiero que se devuelva el attr getter de la clase base. A.attr devuelve un objeto de propiedad (¡que probablemente esté muy cerca de lo que necesito!).

Editar:
Después de recibir la respuesta por debajo de Ned me ocurrió lo que creo que es una solución más elegante a este problema.

class A: 
    @property 
    def attr(self): 
     try: 
      return self._attr 
     except AttributeError: 
      return '' 

class B(A):   
    @A.attr.setter 
    def attr(self, value): 
     self._attr = value 

if __name__ == '__main__': 
    b = B() 
    print('Before set:', repr(b.attr)) 
    b.attr = 'abc' 
    print(' After set:', repr(b.attr)) 

El .setter decorador espera un objeto de propiedad que podemos conseguir utilizando @A.attr. Esto significa que no tenemos que volver a declarar la propiedad en la clase secundaria.

(! Esta es la diferencia entre trabajar en un problema al final del día frente a trabajar en él al comienzo del día)

+0

que tenían el mismo problema, y ​​puede confirmar sus obras respuesta, pero ¡qué $ hitty "característica" - Añadir el nombre de vinculación superclase! !! Ese es un diseño pobre por parte de Python. O eso, o "reimplementar" la propiedad. O son malas "soluciones" a la herencia. – Marc

Respuesta

4

Creo que desee:

class B(A): 
    @property 
    def attr(self): 
     return super(B, self).attr 

Usted menciona que quiere devolver el getter de la clase padre, pero necesita invocar el getter, no devolverlo.

+0

esto no funciona para mí, sin embargo, si llamo 'super(). Attr' consigo el efecto deseado. ¿Es eso algo sabio de hacer? – casr

+0

Ah, tienes razón, porque .attr de los padres no está disponible como un invocable getter más, sólo como una propiedad. super() es la forma de acceder a los mismos atributos de las clases principales. ¿Por qué sería algo poco sabio hacer? –

+0

Simplemente comprobando. No tenía una razón en contra. Actualice su respuesta para que tenga 'super(). Attr' en lugar de' super (B, self) .attr() 'y lo marcaré como respondido :) ¡Gracias por la pista! – casr

23

Para anular un colocador en Python 2 Hice esto:

class A(object): 
    def __init__(self): 
     self._attr = None 

    @property 
    def attr(self): 
     return self._attr 

    @attr.setter 
    def attr(self, value): 
     self._attr = value 


class B(A): 
    @A.attr.setter 
    def attr(self, value): 
     # Do some crazy stuff with `value` 
     value = value[0:3] 
     A.attr.fset(self, value) 
+0

Curiosamente, 'B' no * tiene * para heredar el getter de' A'. Si 'B' solo se hereda de' object', 'B.attr.fget' devolverá' '. Me preocupaba que a 'A.attr.fset' ahora se le haya asignado una función definida por el usuario. 'A.attr.fset' sigue siendo' None', mientras que 'B.attr.fset' es' '. Así que anulando cualquiera de los miembros de accesibilidad de la propiedad, crea primero una copia de la propiedad. Al menos, eso parece ser lo que está sucediendo. –

+0

Me gusta especialmente cómo mostraste cómo anular solo al colocador. No sabía cómo hacerlo y esto me da un poco más de información sobre el decorador setter. – MrMas

Cuestiones relacionadas