2013-04-25 9 views
7

Podążam za książką Wprowadzenie do komputerów za pomocą języka Python, autor: Ljubomir Perkovic, i mam problem z jednym z przykładów w sekcji rekursji książki. Kod jest w następujący sposób:Używanie print() wewnątrz funkcji rekursywnych w Pythonie3

def pattern(n): 
    'prints the nth pattern' 
    if n == 0: # base case 
     print(0, end=' ') 
    else: #recursive step: n > 0 
     pattern(n-1)   # print n-1st pattern 
     print(n, end=' ') # print n 
     pattern(n-1)   # print n-1st pattern 

, powiedzmy, pattern(1), wyjście powinno być 0 1 0, i powinien on być wyświetlane poziomo. Podczas wywoływania funkcji pattern(1) nic nie zostanie wydrukowane. Ale jeśli po tym następuje instrukcja print bez argumentów, wyniki są wyświetlane.

>>>pattern(1) 
>>>print() 
0 1 0 

Jeśli usunąć end argument print() funkcji wewnątrz funkcji rekurencyjnej, uzyskać poprawny wynik (choć to wyświetla go w pionie):

>>> pattern(1) 
0 
1 
0 

To sprawia, że ​​myślę, że sam kod rekurencyjne jest poprawny (plus potwierdziłem, że był on ze źródła podanego na stronie internetowej książki oraz w arkuszu erraty). Nie jestem jednak pewien, dlaczego instrukcja print nie drukuje danych wyjściowych podczas uruchamiania funkcji, jeśli parametr end jest uwzględniony. Każda pomoc będzie bardzo ceniona.

+0

Ten problem może być IDE specyficzne. Wydaje się, że nie występuje przy użyciu Python3 uruchomionego na Ubuntu/gnome-terminal (lub w IPython + emacs). – unutbu

Odpowiedz

7

Funkcja print nie zawsze opróżnia dane wyjściowe. należy go opróżnić wyraźnie:

import sys 

def pattern(n): 
    'prints the nth pattern' 
    if n == 0: # base case 
     print(0, end=' ') 
    else: #recursive step: n > 0 
     pattern(n-1)   # print n-1st pattern 
     print(n, end=' ') # print n 
     pattern(n-1)   # print n-1st pattern 
    sys.stdout.flush() 

pamiętać, że w python3.3 print ma nowy argument słowa kluczowego flush które można używać do spłukiwania siłą wyjście (a zatem unikać sys.stdout.flush).


Na ogólną nocie bym rozdzielić wyjście ze wzoru, robi, na przykład:

def gen_pattern(n): 
    if n == 0: 
     yield 0 
    else: 
     for elem in gen_pattern(n-1): 
      yield elem 
     yield n 
     for elem in gen_pattern(n-1): 
      yield elem 

def print_pattern(n): 
    for elem in gen_pattern(n): 
     print(elem, end=' ') 
    sys.stdout.flush() 

To sprawia, że ​​kod jest bardziej elastyczny i wielokrotnego użytku, i ma tę zaletę, nazywając flush tylko raz lub możesz też wywołać go raz na każdym z elementów x (tak naprawdę uważam, że print już to robi. Płuka, jeśli próbuje napisać wiele znaków na ekranie).

W python3.3 kod można uprościć trochę:

def gen_pattern(n): 
    if n == 0: 
     yield 0 
    else: 
     yield from gen_pattern(n-1) 
     yield n 
     yield from gen_pattern(n-1) 
+3

Ale brak płukania w powłoce interaktywnej wydaje się dziwny. –

+0

@LevLevitsky Nie, jeśli zrobisz coś w stylu 'pattern (1); time.sleep (10) ' – Bakuriu

+0

To się udało! Dzięki! – gos1

4

Powodem jest to, że kiedy end jest używany z jakiegoś wartość inną niż "\n" to funkcja drukowania gromadzi całą wartość i drukuje wyjście tylko wtedy, gdy ma zostać wydrukowany znak nowej linii lub pętla jest zakończona.

Zobacz różnicę w tych dwóch programów:

In [17]: for x in range(5): 
    print(x,end=" ") 
    if x==3: 
     print(end="\n") 
    sleep(2) 
    ....:  
0 1 2 3 #first this is printed 
4  #and then after a while this line is printed 
In [18]: for x in range(5): 
    print(x,end=" ") 
    if x==3: 
     print(end="\t") 
    sleep(2) 
    ....:  
0 1 2 3  4 #whole line is printed at once