在Python3的递归函数中使用print()

在Python3的递归函数中使用print(),python,recursion,python-3.x,Python,Recursion,Python 3.x,我正在学习Ljubomir Perkovic的《使用Python进行计算的入门》一书,但我对该书递归部分的一个示例感到困惑。代码如下: 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

我正在学习Ljubomir Perkovic的《使用Python进行计算的入门》一书,但我对该书递归部分的一个示例感到困惑。代码如下:

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
例如,对于模式(1),输出应该是
0 1 0
,并且应该水平显示。但是,调用函数
模式(1)
时,不会输出任何内容。但是如果后面是一个没有参数的print语句,则会显示结果

>>>pattern(1)
>>>print()
0 1 0
如果在递归函数中删除
print()
函数的
end
参数,则得到正确的输出(尽管它垂直显示):


这让我认为递归代码本身是正确的(另外,我还确认了它是通过本书网站提供的源代码和勘误表得到的)。但是,如果包含
end
参数,我不确定
print
语句为什么不在函数运行时打印输出。任何帮助都将不胜感激。

打印功能并不总是刷新输出。您应该明确地刷新它:

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()
请注意,在python3.3上,print有一个新的关键字参数
flush
,您可以使用它强制刷新输出(从而避免使用
sys.stdout.flush


一般来说,我会将输出与模式分离,例如:

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()
这使得代码更加灵活和可重用,并且具有只调用一次
flush
的优点,或者您也可以每
x
元素调用一次它(实际上我相信
print
已经这样做了。如果试图在屏幕上写入许多字符,它会刷新)

在python3.3中,代码可以简化一点:

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

原因是当
end
“\n”
以外的值一起使用时,打印功能会累加整个值,并且仅当要打印换行或循环结束时才打印输出

请参见这两个程序中的差异:

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

但在交互shell中不刷新似乎很奇怪。@LevLevitsky,如果您执行类似于
pattern(1)的操作,则不会;time.sleep(10)
此问题可能是特定于IDE的。在Ubuntu/gnome终端(或IPython+emacs)上运行Python3似乎不会发生这种情况。
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