Using print() inside recursive functions in Python3

一笑奈何 提交于 2020-02-23 09:33:46

问题


I am following the book Introduction to Computing Using Python, by Ljubomir Perkovic, and I am having trouble with one of the examples in recursion section of the book. The code is as follows:

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

For, say, pattern(1), the output should be 0 1 0, and it should be displayed horizontally. When calling the function pattern(1), nothing prints out, however. But if this is followed by a print statement without arguments, then the results are displayed.

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

If I remove the end argument of the print() functions inside the recursive function, I get correct output (albeit it displays it vertically):

>>> pattern(1)
0
1
0

This makes me think that the recursive code itself is correct (plus I confirmed it was with the source provided by the book's website, and with the errata sheet). I am not sure, however, why the print statement isn't printing the output as the functions run, if the end parameter is included. Any help would be greatly appreciated.


回答1:


The print function doesn't always flush the output. You should flush it explicitly:

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()

Note that on python3.3 print has a new keyword argument flush that you can use to forcibly flush the output(and thus avoid using sys.stdout.flush).


On a general note I'd decouple the output from the pattern, doing, for example:

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()

This makes the code more flexible and reusable, and has the advantage of calling flush only once, or you could also call it once every x elements(actually I believe print already does this. It flushes if trying to write many characters on the screen).

In python3.3 the code could be simplified a little:

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



回答2:


The reason is that when end is used with some value other than a "\n" then the print function accumulates the whole value and prints the output only when a newline is to be printed or the loop is over.

See the difference in these two programs:

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


来源:https://stackoverflow.com/questions/16224200/using-print-inside-recursive-functions-in-python3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!