递归函数 ------- 在函数内部可以调用自身本身的函数
定义一个计算阶乘的函数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
|