在此函数中:
def print_triangle (sideLength):
if sideLength < 1 :
return
print_triangle (sideLength-1)
print ( "[]"* sideLength)
说明:
print ( "[]"* sideLength)
永远不应该到达,因为指令:
print_triangle (sideLength-1)
会阻止它被访问,因为它不断调用函数,这会将程序的流再次发送到函数的开头,即顶部。而不是让它继续在下面:
print ( "[]"* sideLength)
因此,它将继续这样做,直到变量sideLength
变为零。
然而那句台词:
print ( "[]"* sideLength)
到达并绘制一个三角形,当你用 4 作为参数调用它时......但是怎么做呢?
你可以想象递归调用"树"如下。每个框表示函数的执行上下文,因此每次进行新调用时都会描绘一个新框。最里面的框表示参数为 0 的情况,在这种情况下,函数将返回,关闭内框。但是,最里面的盒子的调用者将能够继续,并且将继续print
指令。
所以这是最初的调用:
print_triangle(4)
┌───────────────────────────────────────────────────────┐
│ sideLength ══ 4 │
│ print_triangle(3): │
│ ┌──────────────────────────────────────────────┐ │
│ │ sideLength ══ 3 │ │
│ │ print_triangle(2): │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ sideLength ══ 2 │ │ │
│ │ │ print_triangle(1): │ │ │
│ │ │ ┌────────────────────────────┐ │ │ │
│ │ │ │ sideLength ══ 1 │ │ │ │
│ │ │ │ print_triangle(0): │ │ │ │
│ │ │ │ ┌───────────────────┐ │ │ │ │
│ │ │ │ │ sideLength ══ 0 │ │ │ │ │
│ │ │ │ │ return │ │ │ │ │
│ │ │ │ └───────────────────┘ │ │ │ │
│ │ │ │ print("[]"*1) │ │ │ │
│ │ │ └────────────────────────────┘ │ │ │
│ │ │ print("[]"*2) │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ │ print("[]"*3) │ │
│ └──────────────────────────────────────────────┘ │
│ print("[]"*4) │
└───────────────────────────────────────────────────────┘
好吧,仔细考虑一下。
def print_triangle (sideLength):
if sideLength < 1 :
return
print_triangle (sideLength-1)
print ( "[]"* sideLength)
print_triangle (4)
首先,它从 4 开始
if 4 < 1 :
return
print_triangle (4-1)
print ( "[]"* 4)
现在,在它打印[]*4
之前,它会再次调用该函数,这次为 3:
if 3 < 1 :
return
print_triangle (3-1)
print ( "[]"* 3)
现在,在它打印掉[]*3
之前,它会再次调用该函数,这次为 2:
if 2 < 1 :
return
print_triangle (2-1)
print ( "[]"* 2)
现在,在它打印掉[]*2
之前,它会再次调用该函数,这次为 1:
if 1 < 1 :
return
print_triangle (1-1)
print ( "[]"* 1)
现在,在它打印掉[]*0
之前,它会再次调用该函数,这次为 0。
现在我们知道,由于零小于 1,它返回到最后一个函数,即 1。
现在我们回到最后一个函数调用。
print ( "[]"* 1)
然后到之前的那个:
print ( "[]"* 2)
然后是之前的那个:
print ( "[]"* 3)
最后是你第一次调用函数:
print ( "[]"* 4)
它在返回基本情况并且函数调用堆栈开始弹出后执行。
如果这样写,交换最后两行:
def print_triangle (sideLength):
if sideLength < 1 :
return
print ( "[]"* sideLength)
print_triangle (sideLength-1)
不同之处在于打印的三角形将颠倒。
指令:
print ( "[]"* sideLength)
永远不应该到达,因为指令:
print_triangle (sideLength-1)
会阻止它被访问,因为它不断调用函数
这是不正确的。首先,"它不断调用函数"是错误的。这只调用函数一次。当函数返回时,它将继续到下一行。
特别是,你有
if sideLength < 1 :
return
因此,一旦sideLength
到达0
函数调用就会返回。
作为一个更具体的例子,让我们看看当你打电话给print_triangle(3)
时会发生什么。首先,我们检查if sideLength < 1
,这是假的,然后我们去print_triangle (sideLength-1)
.
这是递归调用print_triangle(2)
。再次,我们检查if sideLength < 1
.仍然下降,所以我们再次递归print_triangle(1)
.if sideLength < 1
仍然是假的,所以我们用print_triangle(0)
再递归一次。
但现在if sideLength < 1
是真的,所以我们回来了。这使我们回到sideLength
为 1 的调用,但在递归调用之后。要执行的下一行代码是print ( "[]"* sideLength)
,这就是它的执行方式。
打印后,我们再次从函数返回到sideLength
为 2 时。所以我们再次print()
并返回到设置为 3sideLength
。在从顶级呼叫返回之前再打印一次。
如果您不返回该值,则该函数将继续运行,然后重复。所以移动:return print_triangle (sideLength-1)
在print( "[]"* sideLength)
之前.将使 print() 只运行一次