递归函数 ------- 在函数内部可以调用自身本身的函数
定义一个计算阶乘的函数fact(n):
fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n
函数可以写为:
>>> def fact(n): if n==1: return 1 return n*fact(n-1) >>> fact(1) 1 >>>fact(5) 120 >>> fact(100) 93326215443944152681699238856266700490715968264381621 46859296389521759999322991560894146397615651828625369 7920827223758251185210916864000000000000000000000000
如果我们计算 fact(5)
,可以根据函数定义看到计算过程如下:
===> fact(5) ===> 5 * fact(4) ===> 5 * (4 * fact(3)) ===> 5 * (4 * (3 * fact(2))) ===> 5 * (4 * (3 * (2 * fact(1)))) ===> 5 * (4 * (3 * (2 * 1))) ===> 5 * (4 * (3 * 2)) ===> 5 * (4 * 6) ===> 5 * 24 ===> 120
递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。可以试试fact(1000)
:
>>> fact(1000) Traceback (most recent call last): File "<pyshell#40>", line 1, in <module> fact(1000) File "<pyshell#33>", line 4, in fact return n*fact(n-1) File "<pyshell#33>", line 4, in fact return n*fact(n-1) File "<pyshell#33>", line 4, in fact return n*fact(n-1) 。。。 File "<pyshell#33>", line 4, in fact return n*fact(n-1) File "<pyshell#33>", line 2, in fact if n==1: RuntimeError: maximum recursion depth exceeded in comparison
切片
取一个list或tuple的部分元素:
(1):
直接通过索引取值
>>> l=[‘xaioming‘,‘zhangsan‘,‘wangwu‘,‘xiaoxin‘,‘xaiohua‘] >>> [l[0],l[1],l[2]] [‘xaioming‘, ‘zhangsan‘, ‘wangwu‘]
(2):
通过循环取值
>>> r=[] >>> n=3 >>> for i in range(n): r.append(l[i])
>>> r [‘xaioming‘, ‘zhangsan‘, ‘wangwu‘]
(3):
通过切片:
>>> l[0:3] [‘xaioming‘, ‘zhangsan‘, ‘wangwu‘]
l[0:3] 表示从索引0开始,知道索引3为止,但不包括索引3.即索引0,1,2,正好是3个元素。
如果第一个索引是0,还可以省略:
>>> l[:3] [‘xaioming‘, ‘zhangsan‘, ‘wangwu‘]
也可以从索引1开始,取出2个元素出来:
>>> l[1:3] [‘zhangsan‘, ‘wangwu‘]
也可以倒数切片:
>>> l[-1] ‘xaiohua‘
>>> l[-2:] [‘xiaoxin‘, ‘xaiohua‘]
创建一个0-99的数列:
>>> L = list(range(100)) >>> L [0, 1, 2, 3, ..., 99]
取前十个元素:
>>> L[:10] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
后十个元素:
>>> L[-10:] [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
前11-20:
>>> L[11:20] [11, 12, 13, 14, 15, 16, 17, 18, 19]
前10个数,,每两个取一个:
>>> L[0:10:2] [0, 2, 4, 6, 8]
所有数,每5个取一个:
>>> L[0:100:5] [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95] >>> L[::5] [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
>>> L[:] [0, 1, 2, 3, ..., 99]
tuple也是一种list ,只是tuple不可变。tuple也可以切片:
>>> (0,1,2,3,4,5)[:3] (0, 1, 2)
字符串 ‘xxxxx’也可以看做一个list,每个元素就是一个字符。因此,字符串也可以切片
>>> ‘ABCDEFGHIKLMNOPQRST‘[:3] ‘ABC‘ >>> ‘ABCDEFGHIKLMNOPQRST‘[::2] ‘ACEGILNPRT‘
迭代
给定一个list或tuple,我们通过for循环来遍历这个list或tuple,这种遍历我们称为 迭代(lteration)。
Python的for
循环不仅可以用在list或tuple上,还可以作用在其他可迭代对象上。
list这种数据类型虽然有下标,但很多其他数据类型是没有下标的,但是,只要是可迭代对象,无论有无下标,都可以迭代,比如dict就可以迭代:
>>> d = {‘a‘:1,‘b‘:2,‘c‘:3} >>> for key in d: print(key) c b a
因为dict的储存不是按照list的方式顺序排列,所以,迭代出的结果顺序很可能不一样。
默认情况下,dict 迭代的是 key 。如果要迭代 value,可以用
for value in d.values()
如果要同时迭代key和value,可以用
for k,v in d.items()
由于字符串也是可迭代对象。因此,也可以作用与 for 循环:
>>> for ch in ‘ABC‘: print(ch) A B C
如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:
>>> from collections import Iterable >>> isinstance(‘abc‘,Iterable) True >>> isinstance([1,2,3],Iterable) True >>> isinstance(123,Iterable) False
如果要对list实现类似于 c 语言 那样的下标循环怎么办?Python内置的 enumerate 函数 可以把一个list变成索引-元素对,这样就可以在 for 循环中同时迭代索引和元素本身:
>>> for i,value in enumerate([‘A‘,‘B‘,‘C‘]): print(i,value) 0 A 1 B 2 C
上面的for
循环里,同时引用了两个变量,在Python里是很常见的,比如下面的代码:
>>> for x,y in [(1,1),(2,2),(3,3)]: print(x,y) 1 1 2 2 3 3