Czy Można zadeklarować funkcję w Pythonie?
Czy Można zadeklarować funkcję w Pythonie? Chcę posortować listę używając mojej własnej funkcji cmp
, zanim zostanie zadeklarowana.
print "\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])
Uporządkowałem swój kod tak, aby po wywołaniu umieścić definicję metody cmp_configs
. Nie powiodło się z tym błędem:
NameError: name 'cmp_configs' is not defined
Czy jest jakiś sposób, aby" zadeklarować " cmp_configs
metodę przed jej użyciem? To sprawi, że mój kod będzie wyglądał czystiej?
Zakładam, że niektórzy ludzie będą kuszeni, aby powiedzieć mi, że powinienem po prostu zreorganizować moją kod, żebym nie miał tego problemu. Są jednak przypadki, gdy jest to prawdopodobnie nieuniknione, na przykład podczas implementacji niektórych form rekurencji. Jeśli nie podoba Ci się ten przykład, załóżmy, że mam przypadek, w którym jest naprawdę konieczne forward zadeklarować funkcję.
Rozważ ten przypadek, w którym forward-deklarowanie funkcji byłoby konieczne w Pythonie:
def spam():
if end_condition():
return end_result()
else:
return eggs()
def eggs():
if end_condition():
return end_result()
else:
return spam()
Gdzie end_condition
i end_result
zostały wcześniej zdefiniowane.
Jest jedynym rozwiązaniem przeorganizować kod i zawsze stawiać definicje przed wywołaniami?
17 answers
Jeśli nie chcesz definiować funkcji przed użyciem, a zdefiniowanie jej później jest niemożliwe, co powiesz na zdefiniowanie jej w innym module?
Formalnie nadal definiujesz to jako pierwsze, ale jest czyste.Możesz utworzyć rekurencję w następujący sposób:
def foo():
bar()
def bar():
foo()
Funkcje Pythona są Anonimowe, podobnie jak wartości są anonimowe, ale mogą być powiązane z nazwą.
W powyższym kodzie foo()
nie wywołuje funkcji o nazwie foo, wywołuje funkcję, która jest powiązana z nazwą foo
w momencie wywołania. Możliwe jest ponowne zdefiniowanie foo
gdzie indziej, a bar
wywoła nową funkcję.
Twój problem nie może zostać rozwiązany, ponieważ to jak prośba o podanie zmiennej, która nie została zadeklarowana.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-27 00:20:59
To, co możesz zrobić, to zawinąć wywołanie w własną funkcję.
Tak, że
foo()
def foo():
print "Hi!"
Złamie się, ale
def bar():
foo()
def foo():
print "Hi!"
bar()
Będzie działać poprawnie.
Ogólna zasada w Python
to nie , że funkcja powinna być zdefiniowana wyżej w kodzie (jak w Pascal
), ale powinna być zdefiniowana przed jej użyciem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-02 15:30:35
Jeśli uruchomisz skrypt poprzez:
if __name__=="__main__":
main()
Wtedy prawdopodobnie nie musisz się martwić o rzeczy takie jak"forward declaration". Widzisz, interpreter załaduje wszystkie twoje funkcje, a następnie uruchomi funkcję main (). Oczywiście upewnij się, że wszystkie importy są poprawne; -)
Nigdy nie słyszałem czegoś takiego jak" forward declaration " w Pythonie... ale z drugiej strony mogę się mylić; -)Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-19 19:33:53
Jeśli wywołanie cmp_configs znajduje się wewnątrz jego własnej definicji funkcji, powinno być dobrze. Podam przykład.
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.
Ogólnie rzecz biorąc, umieszczenie kodu wewnątrz funkcji (takich jak main ()) rozwiąże problem; wystarczy wywołać main () na końcu pliku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-19 19:38:52
W Pythonie nie ma czegoś takiego jak deklaracja forward. Musisz tylko upewnić się, że twoja funkcja jest zadeklarowana, zanim będzie potrzebna. Zauważ, że ciało funkcji nie jest interpretowane dopóki funkcja nie zostanie wykonana.
Rozważ następujący przykład:
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.
Możesz myśleć, że ciało funkcji jest tylko kolejnym skryptem, który zostanie zinterpretowany po wywołaniu funkcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-19 19:42:13
Przepraszam za ożywienie tego wątku, ale nie była tu omawiana strategia, która może mieć zastosowanie.
Używając reflection można zrobić coś podobnego do forward declaration. Na przykład powiedzmy, że masz sekcję kodu, która wygląda tak:
# 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]()
Więc w ten sposób ustaliliśmy, jaką funkcję chcemy wywołać, zanim zostanie ona faktycznie zdefiniowana, czyli deklaracja forward. W Pythonie wyrażenie globals()[function_name]()
jest takie samo jak foo()
if function_name = 'foo'
z powodów omówione powyżej, ponieważ python musi przeszukać każdą funkcję przed jej wywołaniem. Jeśli ktoś użyje modułu timeit
, aby zobaczyć, jak te dwa stwierdzenia się porównują, mają dokładnie taki sam koszt obliczeniowy.
Oczywiście przykład tutaj jest bardzo bezużyteczny, ale jeśli ktoś ma mieć złożoną strukturę, która wymaga wykonania funkcji, ale musi być zadeklarowana przed (lub strukturalnie nie ma sensu mieć ją później), można po prostu zapisać łańcuch znaków i spróbować wywołać funkcję później.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-22 04:08:36
Nie, Nie wydaje mi się, aby w Pythonie można było zadeklarować funkcję forward-declare.
Wyobraź sobie, że jesteś interpreterem Pythona. Kiedy dojdziesz do linii
print "\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])
Albo wiesz czym jest cmp_configs, albo nie. aby kontynuować, musisz poznaj cmp_configs. Nie ma znaczenia, czy istnieje rekurencja.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-19 19:37:31
Czasami algorytm najłatwiej zrozumieć odgórnie, zaczynając od ogólnej struktury i wnikając w szczegóły.
Możesz to zrobić bez deklaracji forward:
def main():
make_omelet()
eat()
def make_omelet():
break_eggs()
whisk()
fry()
def break_eggs():
for egg in carton:
break(egg)
# ...
main()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-29 10:37:36
# 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()
Wyjście:
Hello, world!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-29 19:32:15
Importuj sam plik. Zakładając, że plik nazywa się test.py:
import test
if __name__=='__main__':
test.func()
else:
def func():
print('Func worked')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-11 09:20:08
Nie możesz zadeklarować funkcji w Pythonie. Jeśli masz uruchamianie logiczne przed zdefiniowaniem funkcji, prawdopodobnie i tak masz problem. Umieść swoją akcję w if __name__ == '__main__'
na końcu skryptu (wykonując funkcję, którą nazwałeś "main", jeśli nie jest trywialna), a Twój kod będzie bardziej modułowy i będziesz mógł go używać jako modułu, jeśli kiedykolwiek będziesz potrzebował.
Również zastąp tę listę wyrażeniem generatora (tj., print "\n".join(str(bla) for bla in sorted(mylist, cmp=cmp_configs))
)
Również nie używaj cmp
, co jest deprecated. Użyj key
i podaj mniej niż funkcję.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-15 17:59:57
" po prostu przeorganizuj mój kod, żebym nie miał tego problemu."Zgadza się. Łatwe do zrobienia. Zawsze działa.
Zawsze możesz podać funkcję przed jej odwołaniem.
"są jednak przypadki, kiedy jest to prawdopodobnie nieuniknione, na przykład przy implementacji niektórych form rekurencji"
Nie widzę, jak to możliwe. Proszę podać przykład miejsca, w którym nie można zdefiniować funkcji przed jej użyciem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-19 19:33:09
Chwileczkę. Kiedy twój moduł osiągnie instrukcję print w twoim przykładzie, zanim cmp_configs
zostanie zdefiniowana, czego dokładnie oczekujesz?
Jeśli Twoje wysłanie pytania za pomocą print naprawdę próbuje przedstawić coś takiego:
fn = lambda mylist:"\n".join([str(bla)
for bla in sorted(mylist, cmp = cmp_configs)])
Wtedy nie ma wymogu zdefiniowania cmp_configs
przed wykonaniem tej instrukcji, po prostu zdefiniuj ją później w kodzie i wszystko będzie dobrze.
Teraz, jeśli próbujesz odwołać się do cmp_configs
jako wartości domyślnej z argumentu do lambda, to jest inna historia:
fn = lambda mylist,cmp_configs=cmp_configs : \
"\n".join([str(bla) for bla in sorted(mylist, cmp = cmp_configs)])
Teraz musisz zdefiniować cmp_configs
zanim dotrzesz do tej linii.
[EDIT-ta następna część okazuje się niepoprawna, ponieważ domyślna wartość argumentu zostanie przypisana podczas kompilacji funkcji i ta wartość będzie używana nawet jeśli zmienisz wartość cmp_configs później.]
Na szczęście, Python jest tak przyjazny dla Typu, Jak to jest, nie obchodzi co zdefiniujesz jako cmp_configs
, więc możesz poprzeć to stwierdzenie:
cmp_configs = None
I kompilator będzie szczęśliwy. Tylko pamiętaj, aby zadeklarować prawdziwe cmp_configs
zanim kiedykolwiek wywołasz fn
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-07 18:15:28
TL;DR: Python does not need forward declarations. Po prostu Umieść wywołania funkcji wewnątrz funkcji Def definicje , a wszystko będzie dobrze.
def foo(count):
print("foo "+str(count))
if(count>0):
bar(count-1)
def bar(count):
print("bar "+str(count))
if(count>0):
foo(count-1)
foo(3)
print("Finished.")
Funkcja rekurencyjna definicje , doskonale z powodzeniem daje:
foo 3
bar 2
foo 1
bar 0
Finished.
Jednak
bug(13)
def bug(count):
print("bug never runs "+str(count))
print("Does not print this.")
Łamie na najwyższym poziomie wywołanie funkcji, która nie została jeszcze zdefiniowana i daje:
Traceback (most recent call last):
File "./test1.py", line 1, in <module>
bug(13)
NameError: name 'bug' is not defined
Python jest językiem interpretowanym, podobnie jak Lisp. Nie ma sprawdzania typu, tylko wywołania funkcji run-time, które kończą się sukcesem, jeśli nazwa funkcji została związana, a kończą się niepowodzeniem, jeśli jest niezwiązana.
Krytycznie, funkcja Def definicja nie wykonuje żadnego z funkcji wewnątrz swoich linii, po prostu deklaruje, z czego będzie składać się ciało funkcji. Znowu, to nawet nie sprawdza typu. Więc możemy to zrobić:
def uncalled():
wild_eyed_undefined_function()
print("I'm not invoked!")
print("Only run this one line.")
I działa doskonale (!), z wyjściem
Only run this one line.
Kluczem jest różnica między definicje i wywołania.
Interpreter wykonuje wszystko, co pojawia się na najwyższym poziomie, co oznacza, że próbuje go wywołać. Jeśli nie jest w definicji.
Twój kod wpada w kłopoty, ponieważ próbowałeś wywołać funkcję, na najwyższym poziomie w tym przypadku, zanim została powiązana.
Rozwiązaniem jest umieszczenie wywołania funkcji spoza najwyższego poziomu wewnątrz definicji funkcji, a następnie wywołanie tej funkcji kiedyś znacznie później.
Biznes o "if _ _ main _ _" jest idiomem opartym na tej zasadzie, ale musisz zrozumieć dlaczego, zamiast po prostu ślepo podążać za nią.
Z pewnością istnieją znacznie bardziej zaawansowane tematy dotyczące funkcji lambda i dynamicznego rebindingu nazw funkcji, ale to Nie to, o co prosił OP. Ponadto można je rozwiązać używając tych samych zasad: (1) defs define a function, they do not invocate their lines; (2) wpadasz w kłopoty, gdy wywołujesz symbol funkcji, który jest niezwiązany.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-28 22:42:24
Python nie obsługuje deklaracji forward, ale powszechnym obejściem tego problemu jest użycie następującego warunku na końcu skryptu/kodu:
if __name__ == '__main__': main()
Z tym odczyta najpierw cały plik, a następnie oceni warunek i wywoła funkcję main (), która będzie w stanie wywołać dowolną zadeklarowaną funkcję forward, ponieważ wcześniej odczytała cały plik. Warunek ten wykorzystuje specjalną zmienną __name__
, która zwraca wartość __main__
za każdym razem, gdy uruchamiamy Kod Pythona z bieżącego pliku (gdy kod był zaimportowany jako moduł, następnie __name__
zwraca nazwę modułu).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-05 17:22:36
Jednym ze sposobów jest utworzenie funkcji obsługi. Zdefiniuj handler na początku i umieść handler pod wszystkimi metodami, które musisz wywołać.
Wtedy, gdy wywołasz metodę obsługi do wywołania funkcji, będą one zawsze dostępne.
Obsługa może przyjąć argument nameOfMethodToCall
. Następnie używa kilku poleceń if do wywołania właściwej metody.
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-05 01:58:48
Tak, możemy to sprawdzić.
Input
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()
Wyjście
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.
Jak wspomniał BJ Homer powyżej, ogólna zasada w Pythonie nie jest taka, że funkcja powinna być zdefiniowana wyżej w kodzie (jak w Pascalu), ale że powinna być zdefiniowana przed jej użyciem.
Mam nadzieję, że to pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-08 04:41:10