2012-01-03 10 views
14

¿Por qué el método __get__ en un python descriptor acepta la clase de propietario como su tercer argumento? ¿Puedes dar un ejemplo de su uso?¿Por qué un descriptor python __get__ método acepta la clase owner como un arg?

El primer argumento (self) es evidente, la segunda (instances) tiene sentido en el contexto del patrón descriptor normalmente se muestra (por ejemplo a seguir), pero nunca he visto la tercera (owner) utilizado. ¿Alguien puede explicar cuál es el caso de uso para él?

Sólo a modo de referencia y respuestas que facilitan esto es el uso típico de descriptores que he visto:

class Container(object): 
    class ExampleDescriptor(object): 
     def __get__(self, instance, owner): 
      return instance._name 
     def __set__(self, instance, value): 
      instance._name = value 
    managed_attr = ExampleDescriptor() 

Dado que instance.__class__ está disponible todo lo que puedo pensar es que la aprobación explícita de la clase tiene algo que hacer con acceder directamente al descriptor de la clase en lugar de a instancias (ex Container.managed_attr). Aun así, no estoy seguro de lo que se podría hacer en __get__ en esta situación.

Respuesta

9

owner se utiliza cuando se accede al atributo desde la clase en lugar de una instancia de la clase, en cuyo caso instance será None.

En su ejemplo de intentar algo así como print(Container.managed_attr) fallaría porque instance es None por lo instance._name, plantearían una AttributeError.

Puede mejorar este comportamiento si comprueba si instance is None, y puede ser útil para iniciar sesión o generar una excepción más útil para saber a qué clase pertenece el descriptor, de ahí el atributo owner. Por ejemplo:

 def __get__(self, instance, owner): 
      if instance is None: 
       # special handling for Customer.managed_attr 
      else: 
       return instance._name 
+1

"registrando o levantando una excepción más útil" Gracias. – Finn

+0

¿Por qué no implementar también atributos de nivel de clase administrados? Por ejemplo, cuando un atributo de datos de clase existente se beneficiaría de ser visto en unidades diferentes. Diga, Room.default_temperature_C, Room.default_temperature_F? ¿No es el caso de uso más obvio, o me falta algo? – max

+0

@max: le falta algo;) - pregunte como una pregunta regular si quiere una respuesta detallada. –

1

Sí, se utiliza para que el descriptor puede ver recipiente cuando se accede Container.managed_attr. Podría devolver algún objeto apropiado para el caso de uso, como un método independiente cuando los descriptores se usan para implementar métodos.

2

Cuando se accede al descriptor desde la clase, instance será None. Si no ha contabilizado esa situación (como su código de ejemplo no lo hace), entonces se producirá un error en ese punto.

¿Qué debería hacer en ese caso? Lo que sea sensato ;) Si nada más tiene sentido, puede seguir el ejemplo de property y devolver el descriptor cuando se accede desde la clase.

+0

¿Alguna posibilidad de que pueda explicar cómo la devolución del descriptor es sensible para la propiedad? – Finn

+2

@Finn: * Algo * está allí, por lo que * algo * debe ser devuelto. Como no hay ninguna instancia para obtener un valor, el objeto descriptor es la siguiente mejor opción. Si tiene un descriptor personalizado con un valor de clase real (predeterminado), debe devolverlo cuando se accede a través de la clase. –

Cuestiones relacionadas