Python,即使递归不应该允许,如何完成指令?



在此函数中:

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() 只运行一次

最新更新