Python 101:内置的递归限制

21CTO导读:Python有一个内置的递归限制,以防止开发人员创建构造不良的递归函数。 一块来了解它的工作原理。

递归是数学与计算机科学的一个重要课题。

在计算机编程语言中,递归指的是调用自身的函数,另一种方法是函数本身调用自己的函数定义方式。

在上大学时,计算机科学技术的教授谈到递归,我收到的第一个警告是,你在编程会意外地创建一个无限循环,它会让你的应用程序挂起。

这是极有可能发生的事情。

当你使用递归时,你的函数可能最终无限地调用自身。因此与任何其他潜在的无限循环一样,我们需要确保有办法摆脱死循环。

大多数递归函数的思想都是将程序分解成更小的部分,我们仍然可以使用相同的函数处理它们。

描述递归的最喜欢的方法通常通过创建阶乘函数来处理。阶乘通常看起来像这样:5!。

你可能也注意到了,号码后面有一个惊叹号,该符号表示它是阶乘,这意味着5! = 5 * 4 * 3 * 2 * 1 或 120。

我们来看一个简单的代码例子。

# factorial.py

def factorial(number):

if number == 0:

return 1

else:

return number * factorial(number-1)

if __name__ == '__main__':

print(factorial(3))

print(factorial(5))

在此代码中,我们检查传入的数字以查看它是否等于0。 如果是,我们返回1。 否则,我们取数字并将其乘以调用相同函数但是数字减1的结果。 我们可以稍微修改一下这段代码,以获得我们递归的次数:

def factorial(number, recursed=0):

if number == 0:

return 1

else:

print('Recursed {} time(s)'.format(recursed))

recursed += 1

return number * factorial(number-1, recursed)

if __name__ == '__main__':

print(factorial(3))

每次我们调用阶乘函数并且数字大于0时,我们打印出我们递归的次数。 你应该看到的最后一个字符串应该是“Recursed 2 times(s)”,因为它只需要使用数字3调用factorial函数两次。

Python的递归限制

在本文开头,我提到过,程序员可能创建一个无限的递归循环。 是的,你可以在某些语言中安全通过,但是Python中实际上有一个递归限制。

我们可以通过执行以下操作自行检查:

>>> import sys

>>> sys.getrecursionlimit()

1000

如果你认为程序的递归限制太少,还可以通过sys模块的setrecursionlimit()函数设置递归限制。

让我们尝试创建一个超过该限制的递归函数,看看会发生什么:

# bad_recursion.py

def recursive():

recursive()

if __name__ == '__main__':

recursive()

当运行此代码后,你应该会看到抛出以下异常:

.

Python会阻止你创建一个以永无止境的递归循环结束的函数。

使用递归展开列表

除了阶乘之外,还有其他一些可以用递归做的事情。 更实际的例子是创建一个嵌套列表的函数。如下代码:

# flatten.py

def flatten(a_list, flat_list=None):

if flat_list is None:

flat_list = []

for item in a_list:

if isinstance(item, list):

flatten(item, flat_list)

else:

flat_list.append(item)

return flat_list

if __name__ == '__main__':

nested = [1, 2, 3, [4, 5], 6]

x = flatten(nested)

print(x)

当你运行此代码时,应该最终得到一个只有整数的List列表,而不是整数列表加一个列表。

当然,还有许多其他有效的方法来展开嵌套列表,例如使用Python的itertools.chain()。

小结

现在,我想你应该基本了解递归的工作原理以及如何在Python中使用了。

Python内置的递归限制,能防止开发人员创建构造不良的递归函数。

我还想指出的是,作为开发人员的这么多年,我认为从未真正需要使用递归来解决问题。当然有很多问题可以在递归函数中找到解决方案,但是Python有很多方法可以做同样的事情,我从来没有觉得有必要这样做。

另外一个注意事项是递归可能很难调试,因为错误发生时很难判断你已经到了什么层级的递归。

希望本篇文章对你能有用,快乐编码!

作者:小本聪

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180918G02XD600?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券