2009-05-16 15 views
15

Ho una classe con un membro di dati complessi che voglio mantenere "statico". Voglio inizializzarlo una volta, usando una funzione. Come Pythonic è qualcosa di simile:Pythonic Way inizializzare (Complex) membri di dati static

def generate_data(): 
    ... do some analysis and return complex object e.g. list ... 

class Coo: 
    data_member = generate_data() 
    ... rest of class code ... 

La funzione generate_data richiede molto tempo per completare e restituisce i dati che rimane costante nel campo di applicazione di un programma in esecuzione. Non voglio che venga eseguito ogni volta che viene creata un'istanza di Coo.

Inoltre, per verificare, finché io non assegnare nulla per data_member in __init__, rimarrà "statico"? Cosa succede se un metodo in Coo aggiunge un valore a data_member (supponendo che sia un elenco) - questa aggiunta sarà disponibile per il resto delle istanze?

Grazie

+0

L'unica cosa non-Python di quel codice è usare un identificatore minuscolo per un nome di classe. –

+0

@Card: Certo che hai ragione, l'ho cambiato :) –

risposta

14

Hai ragione su tutti i fronti. data_member verrà creato una volta e sarà disponibile per tutte le istanze di coo. Se qualche istanza lo modifica, quella modifica sarà visibile a tutte le altre istanze.

Ecco un esempio che dimostra tutto questo, con la sua uscita mostrato alla fine:

def generate_data(): 
    print "Generating" 
    return [1,2,3] 

class coo: 
    data_member = generate_data() 
    def modify(self): 
     self.data_member.append(4) 

    def display(self): 
     print self.data_member 

x = coo() 
y = coo() 
y.modify() 
x.display() 

# Output: 
# Generating 
# [1, 2, 3, 4] 
+0

Che dire di qualcosa al di fuori della classe? –

+0

@Omega: È lo stesso - basta dire "module_data = generate_data()" nell'ambito del modulo. – RichieHindle

6

La dichiarazione verrà eseguita una sola volta data_member = generate_data(), quando class coo: ... viene eseguito. Nella maggior parte dei casi le istruzioni di classe si verificano a livello di modulo e vengono eseguite quando il modulo viene importato. Pertanto, data_member = generate_data() verrà eseguito una sola volta quando si importa il modulo con la classe coo per la prima volta.

Tutte le istanze della classe coo condivideranno data_member e potranno accedervi scrivendo . Qualsiasi modifica apportata a sarà immediatamente visibile da qualsiasi istanza coo. Un'istanza può avere il proprio attributo data_member. Questo attributo può essere impostato digitando self.data_member = ... e sarà visibile solo a quell'istanza. È possibile accedere allo "statico" data_member digitando .

13

Come altri hanno risposto che tu abbia ragione - io aggiungo una cosa di essere a conoscenza di: Se un'istanza modifica l'oggetto stesso, ad esempio

self.data_member.append('foo') 

allora la modifica è visto da il resto delle istanze. Tuttavia, se lo fai

self.data_member = new_object 

poi un nuovo membro istanza viene creata che sostituisce il membro della classe ed è visibile solo a tale istanza, non gli altri. La differenza non è sempre facile da individuare, ad esempio self.data_member += 'foo' rispetto a self.data_member = self.data_member + 'foo'.

Per evitare questo è probabilmente dovrebbe sempre fare riferimento all'oggetto come (non attraverso self).

+0

+1 diversi punti positivi, in particolare sul riferimento come attributo di classe anziché come attributo di istanza. –

Problemi correlati