2016-02-09 12 views
8

una domanda stupida, ma questo mi è bugging (indipendentemente downvotes per la mia imbecillità!): Penso che ho raccolto una paura senza senso dei dati che generano al di fuori di un metodo che utilizza il metodo (senza cambiare), ma non sono sicuro se questo è il caso.modo Pythonic di generare dati al di fuori di un metodo

Diciamo che ho un metodo di myfx, che avrà bisogno di un po 'di dizionario datadex che richiede una lunga operazione da fare, ma sarà comune a tutte le chiamate durante quella sessione. Il modo più semplice, ma non fattibile, è:

def myfx(x,foo): 
    datadex={f:42 for f in foo} #initialise 
    mungeddata=datadex[x]+1 #munge 
    return mungeddata 

ma che farà perdere troppo tempo. Quindi la cosa migliore sarebbe quella di farlo nel campo di applicazione principale una volta come si fa con le variabili di classe:

datadex={f:42 for f in foo} #initialise 
def myfx(x): 
    mungeddata=datadex[x]+1 #munge 
    return mungeddata 

Tuttavia, non so perché, ma mi fanno di tutto per evitare questo. È inelegante, ma non penso che sia così. Generalmente ricorrere alle chiusure:

def initialise(foo): 
    datadex={f:42 for f in foo} #initialise 
    def myfx(x): 
     mungeddata=datadex[x]+1 #munge 
     return mungeddata 
    return myfx 

O peggio fare una lezione. Codigo quasi esclusivamente in Python e JS. La mia ipotesi migliore è che è un ritorno al passato dai miei Perl giorni di codifica -Subconsciously mi ritrovo a scrivere somethinge variabili prima alla Pascal, quindi penso che alcune abitudini indugiare come ombre-, ma questo non spiegherebbe il modo di classe o la chiusura di OO-Perl è completamente differente.

+0

'Non so perché, ma faccio di tutto per evitarlo. E 'poco elegante, ma non credo che sia il case' - Sembra che tu stia istintivamente pensare programmazione funzionale, dove (tra le altre cose) variabili non possono essere cambiati una volta definito – Izkata

+0

(a) Qual è esattamente la tua domanda? (b) Non hai considerato di passare semplicemente 'datadex' come argomento alle funzioni (non vedo metodi qui) che lo usano? – jwodder

+3

Sì, che 'il metodo initialise' è fondamentalmente facendo applicazione funzione parziale. C'è un aiutante per il solo che in [functools] (https://docs.python.org/3/library/functools.html) chiamato [parziale] (https://docs.python.org/3/library/functools. html # functools.partial) – dtanders

risposta

6

Una classe è il modo giusto per incapsulare questo comportamento. Alcuni dati sono condivisi da più chiamate di funzione.

class MungedData(object): 

    def __init__(self, foo): 
     self.datadex = {f:42 for f in foo} 

    def myfx(self, x): 
     return self.datadex[x] + 1 

md = MungedData(somefoo) 
print(md.myfx(arg1)) 
print(md.myfx(arg2)) 

Mentre ci sono certamente altre alternative, questo sta andando essere il metodo più comune e semplice in Python.

2

funzioni Python sono oggetti e possono avere attributi, se non si vuole avere la funzione all'interno di una classe si può fare qualcosa di simile:

def myfx(x): 
    mungeddata=myfx.datadex[x]+1 #munge 
    return mungeddata 
myfx.datadex={f:42 for f in foo} #initialise 

Credo che ciò che si sta cercando di evitare è avere una variabile globale.

+2

Per me sembra che si cerchi di risolvere il problema usando "una forma hacky di OO" come @Brendan Abel lo ha definito nei commenti sopra. Questo ha senso quando OO appropriato non è disponibile, come in JS, ma perché limitarti a quello in Python? – Nico

+0

Il fatto che le funzioni possano assumere attributi è più un incidente di come Python è progettato, piuttosto che una funzionalità da sfruttare. Non sono sicuro di averlo mai visto usato. – chepner

+0

@Nico JS non ha "OO corretto"? Non lo sapevo, tutto quello che ho letto su di esso deve essere sbagliato. Python è multiparadigm, non impone alcuno stile agli sviluppatori e non c'è nulla di sbagliato nelle funzioni gratuite. – imreal

0

se si vuole veramente evitare la programmazione orientata agli oggetti, è possibile fare quanto segue per creare una mappa in cui il get_dict() utilizza un generatore per memorizzare il dict.

def get_dict(): 
    d = {f:42 for f in foo} 
    while True: 
    yield d 

def myfx(x): 
    datadex = get_dict() 
    return datadex[x]+1 #munge 

return myfx 
Problemi correlati