Domanda

È possibile dichiarare in avanti una funzione in Python?Voglio ordinare un elenco utilizzando il mio cmp funzione prima che venga dichiarata.

print "\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])

Ho organizzato il mio codice per inserire la definizione di cmp_configs metodo dopo l'invocazione.Fallisce con questo errore:

NameError: name 'cmp_configs' is not defined

Esiste un modo per "dichiarare" cmp_configs metodo prima del suo utilizzo?Renderebbe il mio codice più pulito?

Presumo che alcune persone saranno tentate di dirmi che dovrei semplicemente riorganizzare il mio codice in modo da non avere questo problema.Tuttavia, ci sono casi in cui ciò è probabilmente inevitabile, ad esempio quando si implementano alcune forme di ricorsione.Se non ti piace questo esempio, supponi che io abbia un caso in cui lo è Veramente necessario per dichiarare una funzione.

Considera questo caso in cui sarebbe necessaria la dichiarazione anticipata di una funzione in Python:

def spam():
    if end_condition():
        return end_result()
    else:
        return eggs()

def eggs():
    if end_condition():
        return end_result()
    else:
        return spam()

Dove end_condition E end_result sono stati precedentemente definiti.

L'unica soluzione è riorganizzare il codice e inserire sempre le definizioni prima delle invocazioni?

È stato utile?

Soluzione

Se non si vuole definire una funzione di prima è usato, e definendolo dopo è impossibile, per quanto riguarda la definizione in qualche altro modulo?

Tecnicamente è ancora definirlo un primo momento, ma è pulito.

Si potrebbe creare una ricorsione come il seguente:

def foo():
    bar()

def bar():
    foo()

funzioni di Python sono anonimi proprio come i valori sono anonimi, però, che può essere associato a un nome.

Nel codice precedente, foo() non chiama una funzione con il nome foo, richiama una funzione che sembra essere legato al nome foo nel punto viene effettuata la chiamata. E 'possibile ridefinire foo da qualche altra parte, e bar sarebbe quindi chiamare la nuova funzione.

Il problema non può essere risolto perché è come chiedere di ottenere una variabile che non è stata dichiarata.

Altri suggerimenti

Che cosa si può fare è quello di avvolgere la chiamata in una funzione propria.

In modo che

foo()

def foo():
    print "Hi!"

si romperà, ma

def bar():
    foo()

def foo():
    print "Hi!"

bar()

sarà funzionante.

La regola generale in Python è non che la funzione è opportuno definire più alto nel codice (come in Pascal), ma che dovrebbe essere definito prima del suo utilizzo.

La speranza che aiuta.

Se rilanciare lo script attraverso il seguente:

if __name__=="__main__":
   main()

allora probabilmente non ci si deve preoccupare di cose come "dichiarazione anticipata". Vedete, l'interprete sarebbe andato a caricare tutte le funzioni e quindi avviare la funzione main (). Naturalmente, assicurarsi di avere tutte le importazioni corretti troppo; -)

Vieni a pensarci bene, non ho mai sentito una cosa come "dichiarazione anticipata" in python ... ma poi di nuovo, potrei sbagliarmi; -)

Se la chiamata a cmp_configs è dentro la propria definizione di funzione, si dovrebbe andare bene. Faccio un esempio.

def a():
  b()  # b() hasn't been defined yet, but that's fine because at this point, we're not
       # actually calling it. We're just defining what should happen when a() is called.

a()  # This call fails, because b() hasn't been defined yet, 
     # and thus trying to run a() fails.

def b():
  print "hi"

a()  # This call succeeds because everything has been defined.

In generale, mettere il vostro codice all'interno funzioni (come main ()) risolverà il problema; basta chiamare main () alla fine del file.

Mi scuso per rilanciare questa discussione, ma non c'era una strategia non discusso qui che può essere applicabile.

Utilizzo di riflessione è possibile fare qualcosa di simile alla dichiarazione anticipata. Per esempio Diciamo che avere una sezione di codice che assomiglia a questo:

# We want to call a function called 'foo', but it hasn't been defined yet.
function_name = 'foo'
# Calling at this point would produce an error

# Here is the definition
def foo():
    bar()

# Note that at this point the function is defined
    # Time for some reflection...
globals()[function_name]()

Quindi, in questo modo abbiamo determinato quale funzione che vogliamo chiamare prima che sia effettivamente definito, in modo efficace una dichiarazione anticipata. In Python il globals()[function_name]() affermazione è lo stesso come se foo() function_name = 'foo' per i motivi di cui sopra, dal momento che deve pitone occhiata ogni funzione prima di chiamare. Se si dovesse utilizzare il modulo timeit per vedere come queste due affermazioni confrontano, hanno esattamente lo stesso costo computazionale.

Naturalmente l'esempio qui è molto inutile, ma se si dovesse avere una struttura complessa che doveva eseguire una funzione, ma deve essere dichiarato prima (o strutturalmente molto senso averlo seguito), si può semplicemente negozio una stringa e cercare di chiamare la funzione più tardi.

No, non credo ci sia un modo per inoltrare-dichiarare una funzione in Python.

Immaginate di essere l'interprete Python. Quando si arriva alla linea

print "\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])

o si sa che cosa cmp_configs è o non è. Per procedere, è necessario conoscere cmp_configs. Non importa se c'è ricorsione.

Non v'è nulla di simile in Python come dichiarazione anticipata. Devi solo fare in modo che la funzione viene dichiarata prima che sia necessario. Si noti che il corpo di una funzione non viene interpretato fino all'esecuzione della funzione.

Si consideri il seguente esempio:

def a():
   b() # won't be resolved until a is invoked.

def b(): 
   print "hello"

a() # here b is already defined so this line won't fail.

Si può pensare che un corpo di una funzione è solo un altro script che sarà interpretato una volta che si chiama la funzione.

A volte un algoritmo è più facile da capire top-down, a partire dalla struttura generale e il drill-down nei dettagli.

È possibile farlo senza dichiarazioni previsionali:

def main():
  make_omelet()
  eat()

def make_omelet():
  break_eggs()
  whisk()
  fry()

def break_eggs():
  for egg in carton:
    break(egg)

# ...

main()

Non è possibile inoltrare-dichiarare una funzione in Python. Se si dispone di logica esecuzione delle funzioni prima di aver definito, probabilmente avete avuto un problema in ogni modo. Metti la tua azione in un if __name__ == '__main__' alla fine dello script (eseguendo una funzione è il nome "principale" se si tratta di non banale) e il codice sarà più modulare e sarete in grado di usarlo come modulo se mai necessario.

Inoltre, sostituire tale elenco di comprensione con un espresso generatore (vale a dire, print "\n".join(str(bla) for bla in sorted(mylist, cmp=cmp_configs)))

Inoltre, non utilizzare cmp, che è deprecato. Utilizzare key e fornire un meno-che funzioni.

Importare il file stesso. Supponendo che il file si chiama test.py:

import test

if __name__=='__main__':
    test.func()
else:
    def func():
        print('Func worked')
# declare a fake function (prototype) with no body
def foo(): pass

def bar():
    # use the prototype however you see fit
    print(foo(), "world!")

# define the actual function (overwriting the prototype)
def foo():
    return "Hello,"

bar()

Output:

Hello, world!

"basta riorganizzare il mio codice in modo che io non ho questo problema." Corretta. Facile da fare. Funziona sempre.

Si può sempre fornire la funzione prima che sia di riferimento.

"Tuttavia, ci sono casi in cui questo è probabilmente inevitabile, per esempio in sede di attuazione di alcune forme di ricorsione"

Non riesco a vedere come questo è anche lontanamente possibile. Si prega di fornire un esempio di un luogo dove non si può definire la funzione prima del suo utilizzo.

Ora aspetta un minuto. Quando il modulo raggiunge l'istruzione di stampa nel tuo esempio, prima di cmp_configs è stato definito, che cosa è esattamente che ci si aspetta che faccia?

Se il distacco di una domanda utilizzando stampa è veramente cercando di rappresentare qualcosa di simile:

fn = lambda mylist:"\n".join([str(bla)
                         for bla in sorted(mylist, cmp = cmp_configs)])

allora non c'è alcun obbligo di definire cmp_configs prima di eseguire questa affermazione, basta definire in un secondo momento nel codice e tutto andrà bene.

Ora, se si sta cercando di fare riferimento cmp_configs come valore di default di un argomento per il lambda, allora questa è una storia diversa:

fn = lambda mylist,cmp_configs=cmp_configs : \
    "\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])

Ora è necessario una variabile cmp_configs definita prima di raggiungere questa linea.

[EDIT -. Questa parte successiva risulta non essere corretta, poiché il valore argomento di default sarà ottenere assegnato quando viene compilata la funzione, e tale valore verrà utilizzato anche se si modifica il valore di cmp_configs seguito]

Fortunatamente, Python viene così Type-accomodante come è, non si cura cosa si definiscono come cmp_configs, quindi si può solo precedere con questa dichiarazione:

cmp_configs = None

E il compilatore sarà felice. Basta essere sicuri di dichiarare il vero cmp_configs prima che mai richiama fn.

Un modo è creare una funzione gestore.Definisci il gestore nella fase iniziale e inserisci il gestore sotto tutti i metodi che devi chiamare.

Quindi, quando invochi il metodo del gestore per chiamare le tue funzioni, queste saranno sempre disponibili.

Il conduttore potrebbe accettare una discussione nameOfMethodToCall.Quindi utilizza una serie di istruzioni if ​​per chiamare il metodo giusto.

Questo risolverebbe il tuo problema.

def foo():
    print("foo")
    #take input
    nextAction=input('What would you like to do next?:')
    return nextAction

def bar():
    print("bar")
    nextAction=input('What would you like to do next?:')
    return nextAction

def handler(action):
    if(action=="foo"):
        nextAction = foo()
    elif(action=="bar"):
        nextAction = bar()
    else:
        print("You entered invalid input, defaulting to bar")
        nextAction = "bar"
    return nextAction

nextAction=input('What would you like to do next?:')

while 1:
    nextAction = handler(nextAction)

Sì, possiamo verificarlo.

Ingresso

print_lyrics() 
def print_lyrics():

    print("I'm a lumberjack, and I'm okay.")
    print("I sleep all night and I work all day.")

def repeat_lyrics():
    print_lyrics()
    print_lyrics()
repeat_lyrics()

Produzione

I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.
I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.
I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.

Come menzionato da BJ Homer nei commenti precedenti, una regola generale in Python non è che la funzione debba essere definita più in alto nel codice (come in Pascal), ma che dovrebbe essere definita prima del suo utilizzo.

Spero che aiuti.

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