2015-10-08 23 views
9

Przeprowadzka do Pythona z C/Java tła, Niedawno miałem do wdrożenia wzajemnej rekursji, ale coś w Pythonie przeszkadza mi:W jaki sposób Python implementuje wzajemną rekursję?

ponieważ program python interpretuje wiersz po wierszu, jeśli mam dwie funkcje jeden po drugim w tym samym pliku python:

def A(n): 
    B(n-1) 
# if I add A(1) here, it gives me an error 
def B(n): 
    if n <= 0: 
     return 
    else: 
     A(n-1) 

Gdy interpreter czyta A, B nie jest jeszcze zdefiniowany, jednak ten kod nie nie dają mi błąd

TL; DR moim rozumieniu jest to, że kiedy def jest interpretowany, Python dodaje wpis do jakiejś nazwy lokalnej przestrzeni locals() z {"function name": function address}, ale jak dla ciała funkcji, to tylko zrobić sprawdzenie składni:

def A(): 
    blabla # this will give an error 

def B(): 
    print x # even though x is not defined, this does not give an error 
    A()  # same as above, NameError is only detected during runtime 
+3

"SyntaxError" zostanie przechwycony podczas kompilacji, ale większość innych błędów ('NameError',' ValueError', itp.) Zostanie przechwyconych tylko w środowisku wykonawczym, a następnie tylko wtedy, gdy ta funkcja zostanie wywołana. – TigerhawkT3

+1

łatwe do sprawdzenia, prawda? 'def f(): błąd sytax' czy produkt jest błędem ... – yurib

Odpowiedz

4

A SyntaxError zostanie złapany w czasie kompilacji, ale większość innych błędów (NameError, ValueError, itd.) Zostaną złowione wyłącznie w czasie wykonywania, a następnie tylko wtedy, gdy funkcja jest wywoływana.

"jeśli napisałem jakąś funkcję, jeśli nie została ona wywołana w moim teście .." - i dlatego powinieneś przetestować wszystko.

Niektóre IDE podnoszą ostrzeżenia w różnych sytuacjach, ale najlepszą opcją jest wciąż przeprowadzanie dokładnych testów samodzielnie. W ten sposób można również sprawdzić, czy nie występują błędy wynikające z czynników, takich jak dane wprowadzane przez użytkownika, których automatyczne kontrole IDE nie będą obejmować.

+0

Właśnie dowiedziałem się, że Python może kompilować WOW ... ale dlaczego python nie sprawdza NameError w czasie kompilacji?coś takiego jak ** def A(): print x ** może być łatwo wykryte bez faktycznego przydzielania pamięci (znasz kompilator c/C++) – watashiSHUN

+0

[ta metoda sprawdzania składni] (http://stackoverflow.com/questions/4284313/how-can-i-check-the-syntax-of-python-script-without-executing-it) również tworzy kod binarny ... jeśli cały _compile_ robi to sprawdzając składnię, to znaczy, że wyjście binarne może mieć dużo błędów, a zatem bezużyteczne? – watashiSHUN

+0

Inne języki mogą również zawierać niepoprawne błędy środowiska wykonawczego. Na przykład w języku Java można typować typ do niepoprawnego typu, a kompilator nie będzie narzekał. Dlatego powinieneś właściwie przetestować swój program, aby nie "miał on wielu błędów" i okazał się "bezużyteczny". – TigerhawkT3

4

Linia B(n-1) mówi "kiedy ta instrukcja jest wykonywana, wyszukaj jakąś funkcję w zasięgu modułu, a następnie wywołaj ją z parametrami n-1". Ponieważ wyszukiwanie odbywa się, gdy funkcja jest wykonywana, można później zdefiniować B.

(Dodatkowo można całkowicie zastąpić B o innej funkcji, a A wywoła nową B później. Ale to może doprowadzić do pewnego zamieszania kodu.)

Jeśli martwisz się o nie łapania wywołań nieistniejące funkcje, możesz spróbować użyć narzędzi do analizy statycznej. Poza tym upewnij się, że testujesz swój kod.

0

Gdy interpreter czyta, B nie jest jeszcze określona, ​​jednak ten kod nie daje mi błąd

Powodem interpreter Pythona nie daje błędu można znaleźć z docs , który jest nazywany forward reference pod względem technicznym:

Rozdzielczość nazw zmiennych wolnych występuje w czasie wykonywania, a nie w czasie kompilacji.