'python 2.7学习笔记(3)'

[TOC]

高级特性

切片

取一个list或者tuple中的元素

1
2
3
4
5
6
7
8
9
10
>>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']

>>> L[0:3] #从索引0开始取,直到索引3为止,但不包括索引3。
['Michael', 'Sarah', 'Tracy']
>>> L[:3]
['Michael', 'Sarah', 'Tracy']
>>> L[-2:]
['Bob', 'Jack']
>>> L[-2:-1]
['Bob']

1
2
3
4
5
6
7
8
9
>>> L = range(100)
>>> L
[0, 1, 2, 3, ..., 99]
#前十个数,每两个取一个
>>> L[:10:2]
[0, 2, 4, 6, 8]
#什么都不写,只写[:]就可以原样复制一个list
>>> L[:]
[0, 1, 2, 3, ..., 99]
1
2
>>> (0, 1, 2, 3, 4, 5)[:3]
(0, 1, 2)
1
2
3
4
>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[::2]
'ACEG'

迭代

任何可迭代对象都可以作用于for循环,包括我们自定义的数据类型,只要符合迭代条件,就可以使用for循环。

1
2
3
4
5
6
>>> for i, value in enumerate(['A', 'B', 'C']):
... print i, value
...
0 A
1 B
2 C
1
2
3
4
5
6
>>> for ch in 'ABC':
... print ch
...
A
B
C
1
2
3
4
5
6
7
>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> for key in d:
... print key
...
a
c
b
1
2
3
4
5
6
7
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> for k, v in d.iteritems():
... print k, '=', v
...
y = B
x = A
z = C

列表生成式

可以快速生成list,代替循环

生成[1x1, 2x2, 3x3, …, 10x10]怎么做?
方法一是循环

1
2
3
4
5
6
>>> L = []
>>> for x in range(1, 11):
... L.append(x * x)
...
>>> L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

列表生成试如下:

1
[x*x for x in range(1,11)]

写列表生成式时,把要生成的元素x * x放到前面,后面跟for循环,就可以把list创建出来

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> [x*x for x in range(1,11) if x%2==0]
[4,16,36,64,100]

>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.iteritems()]
['y=B', 'x=A', 'z=C']

>>> L = ['Hello', 'World', 'IBM', 'Apple']
>>> [s.lower() for s in L]
['hello', 'world', 'ibm', 'apple']
1
2
3
>>> L = ['Hello', 'World', 18, 'Apple', None]
>>> [s.lower() if isinstance(s,str) else s for s in L]
['hello', 'world', 18, 'apple', None]

生成器generator

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。

创建方式有两种
1.直接把一个列表生成式的[]改成(),就可以了

1
2
3
4
5
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g

怎么打印generator呢?可以通过generator的next()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
>>> g.next()
0
>>> g.next()
1
>>> g.next()
4
>>> g.next()
9
>>> g.next()
16
>>> g.next()
25
>>> g.next()
36
>>> g.next()
49
>>> g.next()
64
>>> g.next()
81
>>> g.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

上面这种方法有点难以接受,于是,我们通常用for循环来打印

1
2
3
4
>>> g = (x * x for x in range(10))
>>> for n in g:
... print n
...

2.采用定义函数的方式来定义generator,只不过函数体内要有yield.

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator

求斐波拉契数列

1
2
3
4
5
6
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1

1
2
3
f = fib(6)
f.next()
f.next()
1
2
for i in fib(6):
print i

变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令。