2012-10-11 28 views

risposta

12

Si consiglia di leggere i documenti su quali sono in realtà i descrittori. La versione di Cliff's Notes: i descrittori sono un meccanismo di basso livello che ti permette di collegarti agli attributi di un oggetto a cui si accede. Le proprietà sono un'applicazione di alto livello di questo; cioè, le proprietà sono implementate usando i descrittori. O, meglio ancora, le proprietà sono i descrittori che sono già forniti per te nella libreria standard.

Se è necessario un modo semplice per restituire un valore calcolato da un attributo letto o per chiamare una funzione su una scrittura di attributo, utilizzare il decoratore @property. L'API descrittore è più flessibile, ma meno comoda e probabilmente "eccessiva" e non idiomatica in questa situazione. È utile per casi d'uso più avanzati, come l'implementazione di metodi associati, o metodi statici e di classe; quando è necessario sapere, ad esempio, se è stato effettuato l'accesso tramite l'oggetto type o un'istanza del tipo.

+0

Può valere la pena di notare che python scoraggia l'uso di getter e setter, tranne se necessario ... o non può .. –

+3

@JoranBeasley Non è tanto scoraggiato quanto completamente inutile. Poichè Python ti consente di sovrascrivere l'accesso agli attributi, puoi decidere di averne bisogno in una sottoclasse. Se hai bisogno di una proprietà calcolata, è opportuno usare un getter. In Java/C#, è necessario decidere in anticipo se si desidera consentire l'override dell'accesso a un attributo specifico e prevedere ciò nella parte superiore della gerarchia di classi. Questo è il motivo per cui è comune usare le proprietà in modo pervasivo: è fatto "just in case". – millimoose

9

Ulteriori informazioni su entrambi sono disponibili in here. Ma ecco un semplice esempio tratto dallo stesso libro che cerca di spiegare la differenza risolvendo ciò che essenzialmente è lo stesso problema. Come puoi vedere, l'implementazione usando le proprietà è molto più semplice.

Ci sono diversi modi in cui possiamo attingere ai meccanismi interni di Python per ottenere e impostare i valori degli attributi. La tecnica più accessibile consiste nell'utilizzare la funzione proprietà per definire i metodi get, set ed delete associati al nome di un attributo. La funzione property crea descrittori per te. Una tecnica leggermente meno accessibile, ma più estensibile e riutilizzabile consiste nel definire da sé le classi descrittive. Questo ti consente una notevole flessibilità. A tale scopo, crea una classe che definisce i metodi get, set ed delete e associ la classe descrittore a un nome di attributo.

La funzione di proprietà fornisce un modo pratico per implementare un descrittore semplice senza definire una classe separata. Anziché creare una definizione di classe completa, , possiamo scrivere funzioni di metodo getter e setter e quindi associare queste funzioni a un nome di attributo. esempio

descrittore:

esempio
class Celsius(object): 
    def __init__(self, value=0.0): 
     self.value= float(value) 
    def __get__(self, instance, owner): 
     return self.value 
    def __set__(self, instance, value): 
     self.value= float(value) 

class Farenheit(object): 
    def __get__(self, instance, owner): 
     return instance.celsius * 9/5 + 32 
    def __set__(self, instance, value): 
     instance.celsius= (float(value)-32) * 5/9 

class Temperature(object): 
    celsius= Celsius() 
    farenheit= Farenheit() 
>>> 
oven= Temperature() 
>>> 
oven.farenheit= 450 
>>> 
oven.celsius 
232.22222222222223 
>>> 
oven.celsius= 175 
>>> 
oven.farenheit 
347.0 

Proprietà:

class Temperature(object): 
    def fget(self): 
     return self.celsius * 9/5 + 32 
    def fset(self, value): 
     self.celsius= (float(value)-32) * 5/9 
    farenheit= property(fget, fset) 
    def cset(self, value): 
     self.cTemp= float(value) 
    def cget(self): 
     return self.cTemp 
    celsius= property(cget, cset, doc="Celsius temperature") 
>>> 
oven= Temperature() 
>>> 
oven.farenheit= 450 
>>> 
oven.celsius 
232.22222222222223 
>>> 
oven.celsius= 175 
>>> 
oven.farenheit 
347.0 
+12

Credo che l'implementazione del descrittore di Celsius non sia corretta.Dovresti aver impostato il celsius su 'instance' piuttosto che su' self'; Se crei due oggetti Temperatura, condivideranno lo stesso valore centigrado. –

+0

Ho eseguito il codice 'Descriptor example' e funziona correttamente. Ma non ho capito come 'instance.celsius' sia accessibile nella classe' Farenheit'. Grazie. – has