繁体   English   中英

Python 额外的 print() 影响打印的计数器值

[英]Python additional print() impacts printed counter value

下面提供的代码向我展示了意外和奇怪的行为。 没有注释掉的打印语句,计数器变量的最终值与注释掉的打印语句的值不同。 插入的print()如何影响计数器“cnt”的最终值?

这里的 output 带有打印语句打印:

sys: maxRecursionDepth = 10
  > f(s) 0
>>> f(s) 1
  > f(s) 1
>>> f(s) 2
f() maxRecursionDepth =  2

在这里 output 带有注释掉的打印:

sys: maxRecursionDepth = 10
>>> f(s) 1
>>> f(s) 2
f() maxRecursionDepth =  3

这里的代码为我显示了奇怪的效果,我无法解释它是如何产生的:

from sys import getrecursionlimit, setrecursionlimit
setrecursionlimit(10)
print(f'sys: maxRecursionDepth = {getrecursionlimit()}')
cnt = 0
def f(s):
    global cnt
    #print('  >', s, cnt) # <<< CHANGES the final value of 'cnt' !!!
    cnt += 1
    print('>>>', s, cnt)
    eval(s)
# ---
try:
    f("f(s)")
except RecursionError:
    print(f'f() maxRecursionDepth =  {cnt}')
    # RecursionError: maximum recursion depth exceeded

正如Michael Butscher在评论中已经指出的那样,导致提出问题的混淆的核心是错误地认为只有在 function 中对 function 本身的递归调用可能是RecursionError的原因

递归限制实际上是堆栈帧的最大数量。 每次调用 function(甚至是“打印”)都会临时添加一个堆栈帧。 如果打印调用超出限制,则会引发异常。 如果未注释,则在“cnt”递增之前发生,否则在递增之后发生。

下面的证据表明 RecursionError 可以并且实际上是由print()引起的。

>>> f(s) 1
>>> f(s) 2
Traceback (most recent call last):
  File "test.py", line 151, in <module>
    f("f(s)")
  File "test.py", line 150, in f
    eval(s)
  File "<string>", line 1, in <module>
  File "test.py", line 150, in f
    eval(s)
  File "<string>", line 1, in <module>
  File "test.py", line 149, in f
    print('>>>', s, cnt)
RecursionError: maximum recursion depth exceeded while calling a Python object
# ======================================================================
  > f(s) 0
>>> f(s) 1
  > f(s) 1
>>> f(s) 2
Traceback (most recent call last):
  File "test.py", line 151, in <module>
    f("f(s)")
  File "test.py", line 150, in f
    eval(s)
  File "<string>", line 1, in <module>
  File "test.py", line 150, in f
    eval(s)
  File "<string>", line 1, in <module>
  File "test.py", line 147, in f
    print('  >', s, cnt) # <<< CHANGES the final value of 'cnt' !!!
RecursionError: maximum recursion depth exceeded while calling a Python object

在创建上述两个 Tracebacks 的代码下方。 请注意,您自己运行代码可能会导致另一个结果,因为根据运行此代码时堆栈上已有多少帧,代码可能会在另一条语句处失败,正如上面 Traceback 中指出的那样。

from sys import getrecursionlimit, setrecursionlimit
setrecursionlimit(10)
print(f'sys: maxRecursionDepth = {getrecursionlimit()}')
cnt = 0
def f(s):
    global cnt
    # print('  >', s, cnt) # <<< CHANGES the final value of 'cnt' !!!
    cnt += 1
    print('>>>', s, cnt)
    eval(s)
f("f(s)")

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM