3.3.2.3 Invocare i descrittori

Generalmente, un descrittore � un oggetto attributo che ha un ``comportamento limitato'', cio� accessi ad attributi sovrascritti dai metodi del suo protocollo: __get__(), __set__() e __delete__(). Si definisce descrittore l'oggetto che ha qualcuno di questi metodi definito.

Il comportamento predefinito per l'accesso all'attributo � di ottenere ``get'', impostare ``set'', o cancellare ``delete'' l'attributo dal dizionario dell'oggetto. Per esempio a.x esegue una ricerca vincolata che parte da a.__dict__['x'], procede con type(a).__dict__['x'] e continua attraversando le classi base del type(a), escludendo le metaclassi.

Tuttavia, se il valore cercato � chiaramente un oggetto con definito uno dei metodi descrittori, Python allora pu� sovrascrivere il comportamento predefinito ed invocare, invece, il metodo descrittore. La precedenza con cui ci� avviene dipende da quali metodi descrittori sono stati definiti e da come sono chiamati. Notare che i descrittori vengono invocati solo per gli oggetti o le classi di nuovo stile (quelle che derivano da object() o type()).

L'invocazione pi� comune di un descrittore � il legame a.x. Come gli argomenti vengono assemblati dipende da a:

Chiamata diretta
La chiamata pi� semplice e pi� comune avviene quando il programmatore invoca direttamente un metodo descrittore: x.__get__(a).

Legame ad un'istanza
nel caso di un legame ad un'istanza di un oggetto di nuovo stile, a.x viene trasformato in chiamata: type(a).__dict__['x'].__get__(a, type(a)).

Legame ad una classe
nel caso di un legame ad una classe di nuovo stile, A.x viene trasformato in chiamata: A.__dict__['x'].__get__(None, A).

Super legame
Se a � un'istanza di super, allora il legame super(B, obj).m() ricerca obj.__class__.__mro__ per la classe base A immediatamente prima di B e poi invoca il descrittore mediante la chiamata: A.__dict__['m'].__get__(obj, A).

Per i legami d'istanza, la precedenza con cui avviene l'invocazione del descrittore dipende da come sono definiti i suoi metodi. I descrittori di dati definiscono entrambi __get__() e __set__(). Gli altri descrittori hanno solo il metodo __get__(). I descrittori di dati sovrascrivono sempre una ridefinizione in un dizionario d'istanza. D'altro canto, tutti gli altri descrittori possono essere sovrascritti dalle istanze.

I metodi di Python (compresi staticmethod() e classmethod()) non sono implementati come descrittori di dati. Quindi, le istanze possono ridefinire e sovrascrivere i metodi. Ci� permette alle singole istanze di acquisire comportamenti diversi dalle altre istanze della stessa classe.

La funzione property() viene implememtata come descrittore di dati. Perci� le istanze non possono sovrascrivere il comportamento di una propriet�.

Vedete Circa questo documento... per informazioni su modifiche e suggerimenti.