【问题标题】:Using print() inside recursive functions in Python3在 Python3 的递归函数中使用 print()
【发布时间】:2013-04-19 21:43:48
【问题描述】:

我正在关注 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

例如pattern(1),输出应该是0 1 0,并且应该水平显示。但是,当调用函数 pattern(1) 时,什么都不会打印出来。但是如果后面是不带参数的 print 语句,则会显示结果。

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

如果我删除递归函数中 print() 函数的 end 参数,我会得到正确的输出(尽管它垂直显示):

>>> pattern(1)
0
1
0

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

【问题讨论】:

  • 这个问题可能是 IDE 特有的。使用在 Ubuntu/gnome-terminal(或 IPython+emacs)上运行的 Python3 似乎不会发生这种情况。

标签: python recursion python-3.x


【解决方案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

【讨论】:

    【解决方案2】:

    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)
    

    【讨论】:

    • 但在交互式 shell 中不刷新似乎非常奇怪。
    • @LevLevitsky 如果你做类似pattern(1); time.sleep(10)的事情就不会了
    猜你喜欢
    • 2022-11-30
    • 2018-06-20
    • 1970-01-01
    • 2022-06-29
    • 1970-01-01
    • 2012-04-08
    • 2021-12-10
    • 2019-03-22
    • 1970-01-01
    相关资源
    最近更新 更多