2012-01-03 12 views
14

Perché il metodo __get__ in un python descriptor accetta la classe del proprietario come terzo argomento? Puoi dare un esempio del suo utilizzo?Perché un metodo python descrittore __get__ accetta la classe del proprietario come arg?

Il primo argomento (self) è evidente, il secondo (instances) ha un senso nel contesto del modello descrittore tipicamente mostrato (ex a seguire), ma non ho mai visto il terzo (owner) utilizzato. Qualcuno può spiegare a cosa serve il caso d'uso?

Solo a titolo di riferimento e risposte che facilitano questo è l'uso tipico di descrittori che ho 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() 

Dato che instance.__class__ è disponibile tutto quello che posso pensare è che passa in modo esplicito la classe ha qualcosa da fare con l'accesso diretto al descrittore dalla classe anziché da un'istanza (ex Container.managed_attr). Anche così non sono chiaro su cosa si farebbe in __get__ in questa situazione.

risposta

9

owner viene utilizzato quando si accede all'attributo dalla classe anziché un'istanza della classe, nel qual caso instance sarà None.

Nel tuo esempio di tentare qualcosa di simile print(Container.managed_attr) fallirebbe perché instance è None così instance._name sarebbe sollevare un AttributeError.

È possibile migliorare questo comportamento controllando se instance is None e può essere utile per registrare o generare un'eccezione più utile per sapere a quale classe appartiene il descrittore, da cui l'attributo owner. Per esempio:

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

"registrazione o aumento di un'eccezione più utile" Grazie. – Finn

+0

Perché non implementare anche gli attributi a livello di classe gestiti? Ad esempio, quando un attributo di dati di classe esistente trarrebbe vantaggio dall'essere visto in diverse unità. Dì, Room.default_temperature_C, Room.default_temperature_F? Non è il caso d'uso più ovvio, o mi manca qualcosa? – max

+0

@max: ti manca qualcosa;) - chiedi come una domanda regolare se vuoi una risposta dettagliata. –

1

Sì, è utilizzato in modo che il descrittore può vedere contenitore quando Container.managed_attr si accede. È possibile restituire un oggetto appropriato al caso d'uso, come un metodo non associato quando i descrittori vengono utilizzati per implementare i metodi.

2

Quando si accede al descrittore dalla classe, instance sarà None. Se non hai tenuto conto di quella situazione (poiché il codice di esempio non lo fa), allora si verificherà un errore a quel punto.

Cosa deve fare in questo caso? Qualunque cosa sia ragionevole ;) Se nient'altro ha senso, è possibile seguire l'esempio di property e restituire il descrittore stesso quando si accede dalla classe.

+0

Qualche possibilità di spiegare come restituire il descrittore è ragionevole per la proprietà? – Finn

+2

@Finn: * Qualcosa * è lì, quindi * qualcosa * deve essere restituito. Poiché non esiste un'istanza per ottenere un valore, l'oggetto descrittore è la scelta migliore successiva. Se si dispone di un descrittore personalizzato con un valore di classe effettivo (predefinito), è necessario restituirlo quando vi si accede tramite la classe. –

Problemi correlati