Domanda

Sto scrivendo un programma che utilizza tecniche genetiche ad evolversi equazioni. Voglio essere in grado di presentare la funzione 'mainfunc' al Python Parallel 'submit' la funzione. La funzione 'mainfunc' chiama due o tre metodi definiti nella classe Utility. Essi istanziare altre classi e chiamano i vari metodi. Penso che quello che voglio è tutto in uno spazio dei nomi. Così ho istanziato alcuni (forse dovrebbe essere tutto) delle classi all'interno della funzione 'mainfunc'. Chiamo il metodo Utility 'generare ()'. Se dovessimo seguire è la catena di esecuzione si tratterebbe di tutte le classi e metodi nel codice.

Ora, le equazioni sono memorizzati in un albero. Ogni volta che un albero è generato, mutato o croce allevati, i nodi devono essere data una nuova chiave di modo che possano essere accessibili da un attributo dizionario dell'albero. Il 'KeySeq' classe genera questi tasti.

In Python parallelo, ho intenzione di inviare più istanze di 'mainfunc' alla funzione 'Invia' di PP. Ognuno deve essere in grado di accedere 'KeySeq'. Sarebbe bello se tutti si accede alla stessa istanza di KeySeq in modo che nessuno dei nodi sugli alberi restituiti aveva la stessa chiave, ma ho potuto andare in giro che, se necessario.

Quindi: la mia domanda è di circa ripieno tutto in mainfunc. Grazie (Edit) Se non includo tutto in mainfunc, devo provare a raccontare PP sulle funzioni dipendenti, ecc passando varie arguements in vari luoghi. Sto cercando di evitare che.

(fine Edit) se ks.next () viene chiamato all'interno della 'funzione di generare (), che restituisce l'errore 'NameError: nome globale 'ks' non è definito'

class KeySeq:
    "Iterator to produce sequential \
    integers for keys in dict"
    def __init__(self, data = 0):
        self.data = data
    def __iter__(self):
        return self
    def next(self):
        self.data = self.data + 1
        return self.data
class One:
    'some code'
class Two:
    'some code'
class Three:
    'some code'
class Utilities:
    def generate(x):
        '___________'
    def obfiscate(y):
        '___________'
    def ruminate(z):
        '__________'


def mainfunc(z):
    ks = KeySeq()
    one = One()
    two = Two()
    three = Three()
    utilities = Utilities()
    list_of_interest = utilities.generate(5)
    return list_of_interest

result = mainfunc(params)
È stato utile?

Soluzione

Se si desidera che tutte le istanze di mainfunc di utilizzare lo stesso oggetto KeySeq, è possibile utilizzare il trucco valore del parametro predefinito:

def mainfunc(ks=KeySeq()):
   key = ks.next()

Fino a quando in realtà non passa in un valore di ks, tutte le chiamate a mainfunc utilizzerà l'istanza di KeySeq che è stato creato quando è stata definita la funzione.

Ecco il motivo per cui, nel caso in cui non si sa: Una funzione è un oggetto. Ha gli attributi. Uno dei suoi attributi è denominato func_defaults; si tratta di una tupla contenente i valori di default di tutti gli argomenti a sua firma che hanno valori di default. Quando si chiama una funzione e non si fornisce un valore per un argomento che ha un valore predefinito, la funzione recupera il valore da func_defaults. Così, quando si chiama mainfunc senza fornire un valore per ks, ottiene l'istanza KeySeq() fuori della tupla func_defaults. Il che, per tale istanza di mainfunc, è sempre la stessa istanza KeySeq.

Ora, si dice che si sta andando a trasmettere "più istanze di mainfunc alla funzione submit di PP." Vuoi davvero dire più istanze? Se è così, il meccanismo che sto descrivendo non funzionerà.

Ma è difficile da creare più istanze di una funzione (e il codice che hai postato non lo fa). Ad esempio, questa funzione non restituire una nuova istanza di g ogni volta si chiama:

>>> def f():
        def g(x=[]):
            return x
        return g
>>> g1 = f()
>>> g2 = f()
>>> g1().append('a')
>>> g2().append('b')
>>> g1()
['a']
>>> g2()
['b']

Se chiamo g() senza argomenti, restituisce il valore di default (inizialmente una lista vuota) dalla sua tupla func_defaults. Dal momento che g1 e g2 sono diverse istanze della funzione g, il loro valore di default per l'argomento x è anche un'istanza diversa, che quanto sopra dimostra.

Se vuoi per rendere questo più esplicito rispetto all'utilizzo di un ingannevole effetto collaterale di valori di default, ecco un altro modo per farlo:

def mainfunc ():       se non hasattr (mainfunc, "K"):           SetAttr (mainfunc, "K", KeySeq ())       key = mainfunc.ks.next ()

Infine, un punto super importante che il codice che hai postato affaccia: Se avete intenzione di fare l'elaborazione parallela su dati condivisi, il codice che tocca i dati deve attuare bloccaggio. Guardate l'esempio callback.py nella documentazione Python parallela e vedere come blocco viene utilizzato nella classe Sum, e perché.

Altri suggerimenti

E 'bene per strutturare il programma in questo modo. Un sacco di utility a riga di comando seguono lo stesso schema:

#imports, utilities, other functions

def main(arg):
    #...

if __name__ == '__main__':
    import sys
    main(sys.argv[1])

In questo modo è possibile richiamare la funzione main da un altro modulo importando, oppure è possibile eseguirlo dalla riga di comando.

Il tuo concetto di classi in Python non è il suono che penso. Forse, sarebbe una buona idea per rivedere le nozioni di base. Questo collegamento sarà di aiuto.

Python Basics - Classi

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top