我认为我理解递归函数和切片(单独)的基本原理,但我无法将它们组合在一起。我不明白将切片或列表传递给以下函数时会发生什么。
def listSum(ls):
# Base condition
if not ls:
return 0
# First element + result of calling `listsum` with rest of the elements
return ls[0] + listSum(ls[1:])
listSum([1, 3, 4, 5, 6])
19
这是包含此代码的线程: Understanding recursion in Python
我想我会真正受益于调用函数时会发生的事情。
该线程有很多不同的递归函数的例子,具有预期的输出。我理解后面的例子甚至比上面复制的例子还少。
答案 0 :(得分:0)
递归的基本概念是每次调用消耗输入的一部分,减少它直到它匹配基本情况。
此处,基本情况为if not ls
,当ls
为空列表时为真。
消耗是通过切片完成的:每个调用都传递一个比最后一个短一个元素的列表。这是通过listSum(ls1:])
完成的,listSum
在由ls 的所有元素组成的列表上调用ls
,除了第一个。
然后将第一个元素添加到递归调用的结果中并返回。由于ls
元素会有一次递归调用,{{1}}中的每个数字轮流都会被弹出并求和,即消耗。
一步一步地完成它,我们将添加
1 + listSum([3,4,5,6])
是
1 + 3 + listSum([4,5,6])
是
1 + 3 + 4 + listSum([5,6])
是
1 + 3 + 4 + 5 + listSum([6])
是
1 + 3 + 4 + 5 + 6 + listSum([])
,由于基本情况,
1 + 3 + 4 + 5 + 6 + 0
这是19。
答案 1 :(得分:0)
列出遍历宝贝步骤
对于使用递归遍历列表,只有3件事情重要
好的,这是我们用来编写程序的函数
def is_empty (ls):
return ls == []
def head (ls):
return ls[0]
def tail (ls):
return ls[1:]
功能的使用很简单
is_empty ([]) # => True
is_empty ([ 1, 2, 3 ]) # => False
head ([ 1, 2, 3 ]) # => 1
tail ([ 1, 2, 3 ]) # => [2,3]
好的,让我们编写我们的list_sum
函数 - 我想你会同意我们最终得到一个非常易读的程序,这要归功于我们定义的列表助手
def list_sum (ls):
if is_empty (ls):
return 0
else:
return head (ls) + list_sum (tail (ls))
print (list_sum ([ 1, 2, 3, 4, 5, 6, 7 ]))
# => 28
但是您使用尾递归标记了这一点,因此在可选参数和默认值的帮助下,我们可以将递归调用移动到尾部位置。 粗体
的变化def list_sum (ls, acc = 0):
if is_empty (ls):
return acc
else:
return list_sum (tail (ls), head (ls) + acc)
print (list_sum ([ 1, 2, 3, 4, 5, 6, 7 ]))
# => 28
但是Python并没有真正消除尾部调用,所以你仍然需要something else来确保堆栈安全。
每天吸烟高阶函数
使用head
和tail
使我们摆脱了[0]
和[1:]
的乏味(和丑陋),但这种列表遍历的模式非常普遍,我们可以解除我们甚至完全在这个层面上思考!
让我们回顾一下我们的函数list_sum
。此函数遍历列表并使用内置+
函数执行添加。如果我们想要使用+
而不是*
来代替所有元素,那该怎么办?
def list_sum (ls):
if is_empty (ls):
return 0
else:
return head (ls) + list_sum (tail (ls))
def list_product (ls):
if is_empty (ls):
return 1
else:
return head (ls) * list_product (tail (ls))
print (list_product ([ 1, 2, 3, 4, 5, 6, 7 ]))
# => 5040
唯一不同的是0
更改为1
而+
更改为*
。每次我们想要对列表执行某些操作时,我们都不想重写所有这些内容。如果我们使用函数参数抽象这些值,我们可以在这个漂亮的小程序中捕获列表遍历的本质
from operator import add, mul
def list_reduce (f, acc, ls):
if is_empty (ls):
return acc
else:
return list_reduce (f, f (acc, head (ls)), tail (ls))
def list_sum (ls):
return list_reduce (add, 0, ls)
def list_product (ls):
return list_reduce (mul, 1, ls)
print (list_sum ([ 1, 2, 3, 4, 5, 6, 7 ]))
# => 28
print (list_product ([ 1, 2, 3, 4, 5, 6, 7 ]))
# => 5040
可以使用其他高阶函数构建高阶函数。然后在你知道它之前,你正在进行各种高级转换和遍历!
请注意我们此时并未考虑head
或tail
。像not []
,ls[0]
和ls[1:]
这样难以处理的事情是不可见的,因此是不可思议的。
def map (f, ls):
return list_reduce (lambda acc, x: acc + [ f (x) ], [], ls)
def square (x):
return x * x
print (map (square, [ 1, 2, 3, 4, 5, 6, 7 ]))
# => [1, 4, 9, 16, 25, 36, 49]