¿Por qué un método del descriptor python __get__ acepta la clase del propietario como un argumento?

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

El primer argumento ( self ) es evidente por sí mismo, el segundo ( instances ) tiene sentido en el contexto del patrón descriptor típicamente mostrado (a continuación), pero nunca he visto realmente usado el tercer ( owner ). ¿Alguien puede explicar cuál es el caso de uso para ello?

Solo a modo de referencia y de facilitar respuestas, este es el uso típico de los 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 la instance.__class__ está disponible, todo lo que puedo pensar es que pasar la clase explícitamente tiene algo que ver con acceder directamente al descriptor de la clase en lugar de a las instancias (ex Container.managed_attr ). Aun así, no tengo claro qué haría uno en __get__ en esta situación.

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

En su ejemplo, intentar algo como print(Container.managed_attr) fallaría porque la instance es None por lo que instance._name generaría un AttributeError .

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

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

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

¿Qué debes hacer en ese caso? Lo que sea sensible. 😉 Si nada más tiene sentido, puede seguir el ejemplo de la property y devolver el descriptor cuando se acceda desde la clase.

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