[英]Passing a slice to recursive function in Python
我想我了解递归函数和切片的基本原理(分别),但是我很难将它们组合在一起。 我不明白将切片或列表传递给以下函数时会发生什么。
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
这是包含以下代码的线程: 了解Python中的递归
我想我真的将从逐步了解调用该函数时发生的事情中受益。
该线程具有许多不同的递归函数示例,并具有预期的输出。 我理解的后续示例甚至比我上面复制的示例少。
递归的基本概念是,每次调用都消耗部分输入,并减少输入直到匹配基本情况 。
在这里,基本情况是if not ls
,当ls
为空列表时将为true。
消耗是通过切片来完成的:每个调用都传递一个比最后一个元素短一个元素的列表。 这是通过listSum(ls1:])
,该listSum
在由ls的所有元素( 第一个元素除外)组成的列表上调用listSum
。
然后,将第一个元素添加到递归调用的结果中并返回。 因为将会有一个递归调用用于元件ls
,在各编号ls
得到在转弯是一个弹出并求和,即, 消耗掉 。
逐步进行操作,我们将添加
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。
列出遍历婴儿的步骤
对于使用递归遍历列表,只有三件事很重要
好的,这是我们用来编写程序的函数
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实际上并没有消除尾部调用的功能,因此您仍然必须做其他事情以确保堆栈安全。
每天吸烟高阶功能
使用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]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.