2010-05-04 14 views
9

Recentemente ho scoperto Python property built-in, che nasconde i getter ei setter del metodo di classe come proprietà di una classe. Ora sono tentato di usarlo in modi che sono abbastanza sicuri sono inappropriati.Quando utilizzare la "proprietà" integrata: funzioni ausiliarie e generatori

Utilizzare la parola chiave property è chiaramente la cosa giusta da fare se la classe A ha una proprietà _x di cui si desidera limitare i valori consentiti; cioè, sostituirebbe la costruzione getX() e setX() che si potrebbe scrivere in C++.

Ma dove altro è opportuno rendere una funzione una proprietà? Ad esempio, se si dispone di

class Vertex(object): 
    def __init__(self): 
     self.x = 0.0 
     self.y = 1.0 

class Polygon(object): 
    def __init__(self, list_of_vertices): 
     self.vertices = list_of_vertices 
    def get_vertex_positions(self): 
     return zip(*((v.x,v.y) for v in self.vertices)) 

è opportuno aggiungere

vertex_positions = property(get_vertex_positions) 

?

È mai ok per far sembrare un generatore una proprietà? Immagina se un cambiamento nel nostro codice significasse che non abbiamo più memorizzato Polygon.vertices allo stesso modo. Sarebbe quindi ok aggiungere questo a Polygon?

@property 
    def vertices(self): 
     for v in self._new_v_thing: 
      yield v.calculate_equivalent_vertex() 

risposta

14
  • Quando si ha un attributo normale e l'acquisizione e/o l'impostazione ha senso per l'utente di una classe, esporre direttamente l'attributo. Uno dei motivi principali per cui i membri pubblici sono anatemi in alcune lingue è che se devi fare qualcosa di più complesso in un secondo momento, avrai bisogno di un cambio API; in Python puoi semplicemente definire una proprietà.

  • Se si utilizza qualcosa che si dovrebbe astrarre come accesso agli attributi, utilizzare la proprietà. Se si desidera rendere noto lo stato esterno (la trama o il sito Web o qualcosa del genere) o se si sta eseguendo il wrapping di una libreria che utilizza direttamente i membri, le proprietà potrebbero essere la soluzione.

  • Se qualcosa non è attributo-y, non renderlo una proprietà. Non c'è nulla di male nel fare un metodo, e può essere vantaggioso: quello che fa è più ovvio, è possibile passare un metodo associato se necessario, è possibile aggiungere argomenti di parole chiave senza una modifica API.

    È difficile immaginare una situazione in cui utilizzerei una funzione di generatore come proprietà. L'unico modo per avere un attributo normale che si comporterebbe in modo simile richiederebbe un bel po 'di complessità, così che il caso non ricorda molto l'accesso agli attributi.

  • Si sottolinea che è possibile utilizzare property per limitare l'accesso ad alcuni attributi interni _x. Questo può essere vero, ma tenere a mente

    • Se avete intenzione di fare le cose come ingresso disinfettare per la sicurezza o di qualcosa di importante, esplicito è meglio che implicita.Non vuoi sentirti come se il codice funzioni correttamente quando si tratta di cose del genere, perché allora ti imbatterai in codice che non funziona.

    • A volte le persone utilizzano property per implementare attributi di sola lettura. Di solito è meglio avere un attributo normale e rendersi conto che non si può impedire a un utente di fare qualcosa di stupido e non supportato.

  • nitpicking potreste trovare interessante:

    • property non è una parola chiave; è un nome normale che puoi riassociare. Questa è una specie di interessante dal momento che property non è una cosa di sintassi o altro: è una classe normale che potresti implementare in puro Python. Utilizza lo stesso meccanismo che fa funzionare i metodi in Python- descriptors.

    • Descrivi cosa property fa come "nasconde getter e setter del metodo di classe", il che non è proprio il caso. Le cose che property prendono sono solo funzioni normali e non devono essere effettivamente definite nella classe; property passerà per te self. Le funzioni in realtà non diventano metodi fino a quando non vengono cercati, quando Python crea oggetti metodo al volo. Durante la definizione della classe, sono solo funzioni. Quando hai un metodo normale è chiamato "metodo di istanza"; in Python "metodo di classe" si riferisce a another special thing una sorta di proprietà simili che cambia ciò che accade quando viene rilevato un attributo.

2

C'è una limitazione evidente nell'uso della proprietà: non accetta alcun argomento, e non potrà mai fare.

Quindi è necessario essere certi che la funzione che si sta trasformando in una proprietà non verrà mai refactored in una funzione con, ad esempio, argomenti di default aggiuntivi.

Problemi correlati