2013-06-09 13 views
11

Mi sono chiesto da un po 'se esiste un modo più semplice per assegnare gli attributi di classe al metodo spazio dei nomi locale. Per esempio, in dosomething metodo, ho esplicitamente fare riferimenti a self.a e self.b:Python che importa gli attributi di classe nel namespace del metodo locale

class test: 
    def __init__(self): 
     self.a = 10 
     self.b = 20 

    def dosomething(self): 
     a = self.a 
     b = self.b 
     return(a + b) 

Ma a volte ho un sacco di variabili (più di 10) e diventa disordinato di digitare e guardare - avrei grappolo delle istruzioni var = self.var all'inizio di un metodo.

C'è un modo per farlo in modo più compatto? (So ​​che l'aggiornamento local() non è una buona idea)

Edit: Idealmente, quello che voglio è:

def dosomething(self): 
    populate_local_namespace('a', 'b') 
    return(a + b) 
+0

Perché stai provando a fare questo in primo luogo?Cosa c'è di sbagliato nell'avere un metodo 'dosomething' a una riga che assomiglia a" return (self.a + self.b) '"? Quale beneficio ti aspetti di ottenere da questo? – rmunn

+3

Ho le mie ragioni - in particolare, sto facendo calcoli complessi e molti "self" rendono le espressioni molto lunghe e brutte. – joon

risposta

21

D. Esiste un modo per fare questo modo più compatto?

1. Se le variabili sono di sola lettura, sarebbe ragionevolmente Pythonic di fattore-out di un metodo di accesso multi-variabile:

class Test: 

    def __init__(self): 
     self.a = 10 
     self.b = 20 
     self.c = 30 

    def _read_vars(self): 
     return self.a, self.b, self.c 

    def dosomething(self): 
     a, b, c = self._read_vars() 
     return a + b * c 

    def dosomethingelse(self): 
     a, b, c = self._read_vars() 
     return a - b * c 

Se le variabili non sono di sola lettura , è meglio attenersi a self.inst_var = value. Questo è il modo normale di scrivere codice Python e di solito è quello che la maggior parte della gente si aspetta.


2. Di tanto in tanto si vedrà persone abbreviare self con un nome di variabile più breve. Viene utilizzato quando i benefici leggibilità del decluttering superano il costo di leggibilità utilizzando un nome variabile non standard:

def updatesomethings(s): 
    s.a, s.b, s.c = s.a + s.c, s.b - s.a, s.c * s.b 

3. altro modo per gestire una variabile gran numero di istanza è a memorizzarle in un contenitore mutabile per la facilità di fare e disfare:

class Test: 

    def __init__(self, a, b, c, d, e, f, g, h, i): 
     self._vars = [a, b, c, d, e, f, g, h, i] 

    def fancy_stuff(self): 
     a, b, c, d, e, f, g, h, i = self._vars 
     a += d * h - g 
     b -= e * f - c 
     g = a + b - i 
     self._vars[:] = a, b, c, d, e, f, g, h, i 

4. There i s anche un approccio manipolazione dizionario che avrebbe funzionato, ma ha un odore di codice che la maggior parte Pythonisti eviterebbero:

def updatesomethings(self): 
    a = 100 
    b = 200 
    c = 300 
    vars(self).update(locals()) 
    del self.self 
+0

Grazie. In realtà questo è esattamente quello che ho fatto. Ma questo non è abbastanza flessibile, dal momento che quando voglio cambiare le variabili devo cambiare entrambe le posizioni. Sarebbe bello se ci fosse un modo in cui posso semplicemente passare il nome di un attributo a una funzione come una stringa e l'attributo diventa una variabile locale. – joon

+0

@joon Ho aggiunto anche altre opzioni per te. –

+0

Sì 4 sembra spaventoso :) Per il momento utilizzerei semplicemente la modalità di chiamata ('_read_vars()'). Grazie mille per il vostro aiuto!! – joon

-2

si può facilmente risolvere questo problema con un compromesso, memorizzando le variabili in un dizionario.

data = {} 
copy_to_local_variables = ["a", "b", "c", "d"] 
for var_name in copy_to_local_variables: 
    data[var_name] = getattr(self, var_name) 

(Anche se io riesco a capire il motivo per cui è necessario copiare gli attributi di classe per il metodo namespace locale)

+1

Questo non farà semplicemente un dict chiamato 'data' con quelle variabili invece di fare variabili locali che fanno riferimento ad attributi di classe? Non penso che questo sia quello che voglio. – joon

-2

ho trovato un altro modo:

def dosomething(self): 
    for key in ['a', 'b']: 
     exec('{} = self.{}'.format(key, key)) 

    return(a + b) 

Non so se questo è pericoloso o no. Sarebbe bello se qualcuno potesse commentare questo.

+3

Sarebbe pericoloso se la chiave fosse mai una stringa proveniente da una fonte non attendibile. – korylprince

+2

È anche probabile che sia molto lento, poiché ogni volta che viene effettuata la chiamata exec() Python deve eseguire il lex, analizzare, compilare ed eseguire la nuova dichiarazione come se la vedesse per la prima volta. –

+0

Grazie per i commenti! – joon

Problemi correlati