递归函数 ------- 在函数内部可以调用自身本身的函数
定义一个计算阶乘的函数fact(n):
1
2
3
4
|
fact(n) = n!
= 1 x 2 x 3 x ... x (n - 1 ) x n
= (n - 1 )! x n
= fact(n - 1 ) x n
|
函数可以写为:
1
2
3
4
5
6
7
8
9
10
11
12
|
>>> 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)
,可以根据函数定义看到计算过程如下:
1
2
3
4
5
6
7
8
9
10
|
= = = > 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)
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
>>> 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):
直接通过索引取值
1
2
3
|
>>> l = [ 'xaioming' , 'zhangsan' , 'wangwu' , 'xiaoxin' , 'xaiohua' ]
>>> [l[ 0 ],l[ 1 ],l[ 2 ]]
[ 'xaioming' , 'zhangsan' , 'wangwu' ]
|
(2):
通过循环取值
1
2
3
4
|
>>> r = []
>>> n = 3
>>> for i in range (n):
r.append(l[i])
|
1
2
|
>>> r [ 'xaioming' , 'zhangsan' , 'wangwu' ]
|
(3):
通过切片:
1
2
|
>>> l[ 0 : 3 ]
[ 'xaioming' , 'zhangsan' , 'wangwu' ]
|
l[0:3] 表示从索引0开始,知道索引3为止,但不包括索引3.即索引0,1,2,正好是3个元素。
如果第一个索引是0,还可以省略:
1
2
|
>>> l[: 3 ]
[ 'xaioming' , 'zhangsan' , 'wangwu' ]
|
也可以从索引1开始,取出2个元素出来:
1
2
|
>>> l[ 1 : 3 ]
[ 'zhangsan' , 'wangwu' ]
|
也可以倒数切片:
1
2
|
>>> l[ - 1 ]
'xaiohua' |
1
2
|
>>> l[ - 2 :]
[ 'xiaoxin' , 'xaiohua' ]
|
创建一个0-99的数列:
1
2
3
|
>>> L = list ( range ( 100 ))
>>> L [ 0 , 1 , 2 , 3 , ..., 99 ]
|
取前十个元素:
1
2
|
>>> L[: 10 ]
[ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
|
后十个元素:
1
2
|
>>> L[ - 10 :]
[ 90 , 91 , 92 , 93 , 94 , 95 , 96 , 97 , 98 , 99 ]
|
前11-20:
1
2
|
>>> L[ 11 : 20 ]
[ 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 ]
|
前10个数,,每两个取一个:
1
2
|
>>> L[ 0 : 10 : 2 ]
[ 0 , 2 , 4 , 6 , 8 ]
|
所有数,每5个取一个:
1
2
3
4
|
>>> 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 ]
|
1
2
|
>>> L[:] [ 0 , 1 , 2 , 3 , ..., 99 ]
|
tuple也是一种list ,只是tuple不可变。tuple也可以切片:
1
2
|
>>> ( 0 , 1 , 2 , 3 , 4 , 5 )[: 3 ]
( 0 , 1 , 2 )
|
字符串 ‘xxxxx’也可以看做一个list,每个元素就是一个字符。因此,字符串也可以切片
1
2
3
4
|
>>> 'ABCDEFGHIKLMNOPQRST' [: 3 ]
'ABC' >>> 'ABCDEFGHIKLMNOPQRST' [:: 2 ]
'ACEGILNPRT' |
迭代
给定一个list或tuple,我们通过for循环来遍历这个list或tuple,这种遍历我们称为 迭代(lteration)。
Python的for
循环不仅可以用在list或tuple上,还可以作用在其他可迭代对象上。
list这种数据类型虽然有下标,但很多其他数据类型是没有下标的,但是,只要是可迭代对象,无论有无下标,都可以迭代,比如dict就可以迭代:
1
2
3
4
5
6
7
|
>>> d = { 'a' : 1 , 'b' : 2 , 'c' : 3 }
>>> for key in d:
print (key)
c b a |
因为dict的储存不是按照list的方式顺序排列,所以,迭代出的结果顺序很可能不一样。
默认情况下,dict 迭代的是 key 。如果要迭代 value,可以用
1
|
for value in d.values()
|
如果要同时迭代key和value,可以用
1
|
for k,v in d.items()
|
由于字符串也是可迭代对象。因此,也可以作用与 for 循环:
1
2
3
4
5
6
7
|
>>> for ch in 'ABC' :
print (ch)
A B C |
如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:
1
2
3
4
5
6
7
|
>>> from collections import Iterable
>>> isinstance ( 'abc' ,Iterable)
True >>> isinstance ([ 1 , 2 , 3 ],Iterable)
True >>> isinstance ( 123 ,Iterable)
False |
如果要对list实现类似于 c 语言 那样的下标循环怎么办?Python内置的 enumerate 函数 可以把一个list变成索引-元素对,这样就可以在 for 循环中同时迭代索引和元素本身:
1
2
3
4
5
6
|
>>> for i,value in enumerate ([ 'A' , 'B' , 'C' ]):
print (i,value)
0 A
1 B
2 C
|
上面的for
循环里,同时引用了两个变量,在Python里是很常见的,比如下面的代码:
1
2
3
4
5
6
|
>>> for x,y in [( 1 , 1 ),( 2 , 2 ),( 3 , 3 )]:
print (x,y)
1 1
2 2
3 3
|