python递归菜鸟_菜鸟学飞自学Python(三)递归、切片、迭代

(仅个人学习摘录)

递归函数

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

例子,计算阶乘 n! = 1 x 2 x 3 x ... x n,用函数 fact(n) 表示:

fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = fact(n-1) x n

fact(n) 用递归的方式写出来:

def fact(n):

if n==1:

return 1

return n * fact(n-1)

递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑性不如递归清晰。

使用递归要防止栈溢出。在计算机中,函数调用是通过栈实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,把循环看成是一种特殊的尾递归函数也是可以的。

尾递归是指,在函数返回的时候,调用自身本身,并且,return 语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现溢出的情况。

可知,return fact_iter(num-1,num*project) 仅返回递归函数本身,num-1 和 num*project 在函数调用前就会被计算,不影响函数调用。

尾递归调用时,如果做了优化,栈就不会增长,但是编程语言对尾递归调用没有进行优化,所以还是会溢出。

使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。

练习:汉诺塔  recur.py

切片

取一个 list 或 tuple 的部分元素是非常常见的操作。

最简单的方法:

也可以利用循环,但是比较繁琐,Python 提供了切片(slice)操作符,可以简化操作。

取前 3 个元素:

L[0:3] 表示,从索引 0 开始取,知道索引 3 为止,但不包含索引 3。即索引 0、1、2,正好 3 个元素。

如果第一个索引是 0,还可以省略:

也可以不从索引 0 开始:

倒数切片:

倒数第一个元素的索引是 -1。

只写 [:] 可以复制一个 list。

tuple 也可以进行切片操作,操作结果仍是 tuple:

字符串也可以看成是一种 list,也可以进行切片操作,操作结果仍是字符串:

迭代

如果给定一个 list 或 tuple,我们可以通过 for 循环来遍历这个 list 或 tuple,这种遍历称为迭代(Iteration)。

在 Python 中,迭代是通过 for ... in 来完成的,Python 的 for 循环不仅可以用在 list 或 tuple 上,还可以作用在其他可迭代对象上。只要是可迭代对象,无论有无下标,都可以迭代,比如 dict:

因为 dict 的存储不是按照 list 的方式顺序排列,所以,迭代出的结果顺序很可能不一样。默认情况下,dict 迭代的是 key。如果要迭代 value,可以用 for value in d.value(),如果要同时迭代 key 和 value,可以用 for k,v in d.items()。

字符串也是可迭代对象,也可用 for 循环:

判断对象是否可迭代:

通过 collections 模块的 Iterable 类型判断:

Python 内置的 enumerate 函数可以把一个 list 变成索引—元素对,这样就可以在 for 循环中同时迭代索引和元素本身:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值