我刚刚开始学习Python,我不理解在自己内部调用相同函数的能力?
以下是一个例子:
import turtle
from turtle import left, right, forward
size = 10
def hilbert(level, angle):
if level == 0:
return
turtle.color("Blue")
turtle.speed("Fastest")
right(angle)
hilbert(level - 1, -angle)
forward(size)
left(angle)
hilbert(level - 1, angle)
forward(size)
hilbert(level - 1, angle)
left(angle)
forward(size)
hilbert(level - 1, -angle)
right(angle)
这究竟是如何运作的?
感谢。
答案 0 :(得分:3)
答案 1 :(得分:2)
当level
等于0时,hilbert(level,angle)
才会返回,即不执行任何操作。
现在考虑当level
等于1时会发生什么:调用hilbert(1,angle)
执行这些语句:
turtle.color("Blue")
turtle.speed("Fastest")
right(angle)
forward(size)
left(angle)
forward(size)
left(angle)
forward(size)
right(angle)
在我看来,这可能是一个正方形的三面。
自hilbert(level-1,...)
等于0后,level-1
语句已被删除,我们已确定hilbert(0,...)
不执行任何操作。
现在,请考虑致电hilbert(1,-angle)
时会发生什么。
接下来,考虑当level
等于2时会发生什么。我希望这可以让您了解如何继续。
PS。关于Python的可爱之处 - 您可以以交互方式运行程序,以可视化调用hilbert(1,angle)
的功能,然后hilbert(2,angle)
执行,等等...
答案 2 :(得分:1)
这是一种强大的编程技术recursion,通过将问题分解为类似但更小的问题来解决问题,直到问题足够小以便轻松解决为止。
答案 3 :(得分:1)
正如@Tom Zych和其他人所提到的,这是一个称为递归的问题,起初可能难以解决问题(有时需要以与通常完全不同的方式思考问题)。
最经典且易于理解(但不一定有用或强大)的递归示例是阶乘生成器。给定正整数n
,n
的阶乘等于小于或等于n
的所有正整数的乘积。我们将n
的阶乘写为n!
:
N! = n *(n-1)*(n-2)* ... * 3 * 2 * 1
现在通过递归,我们希望看到,“当我尝试解决更大的问题时,这里重复的模式是什么,变得更简单?”我们试试5!
例如:
5! = 5 * 4 * 3 * 2 * 1
解决这个等式时我们做的第一件事是什么?我们采用5
并将其乘以某种东西。这很完美,因为如果我们有一个因子函数fact(n)
,我们可能会将n
作为参数:
def fact(n):
return n * #something
剩下的就是找出#something
是什么。但我们只是在上面写了:
5! = 5 *(4 * 3 * 2 * 1)
但是新的#something
如何只是一个与我们原始问题基本相同的小问题?观察,这是递归的魔力:
5! = 5 * 4 * 3 * 2 * 1
= 5 * 4!
4! = 4 * 3 * 2 * 1
= 4 * 3!
3! = 3 * 2 * 1
= 3 * 2!
2! = 2 * 1
= 2 * 1!
1! = ???
正如您所看到的,对于大多数给定的n
,
N! = n *(n-1)!
我们差不多了,现在我们已经发现了我们的模式,我们需要担心异常情况,最简单的情况,(当n = 1时,没有别的东西可以乘以)。在递归中,我们称之为基本情况,幸运的是,我们确切地知道在这个基本情况下要做什么:1! = 1
。因此,在总结我们的逻辑时,我们可以编写递归因子函数:
def fact(n):
# Take care of the base case first
if n == 1:
return 1
# Then break down the larger case into its recursive sub-problems
else:
return n * fact(n-1)
你的Hilburtle程序有点复杂,但是如果你知道Hilbert曲线分析的一些内容,并且你开始理解递归程序逻辑,那么你应该能够弄清楚它是如何工作的。祝你好运!
答案 4 :(得分:0)
这被称为recursion。递归函数通常可以解决一个小问题,但也能够将较大的问题分解为更容易解决的较小问题。
在你的例子中,看起来程序可能是一些耗费精力的程序。
答案 5 :(得分:0)
实际上这很简单。一般来说,除了一些(重要的,但不是讨论)例外:
换句话说,如果调用不同的函数或递归调用相同的函数,计算机并不在意。实际上,它可以稍微优化递归函数,因为它知道每次都会发生相同的事情,比如for循环。