-
Notifications
You must be signed in to change notification settings - Fork 0
/
高级特性.txt
196 lines (154 loc) · 4.68 KB
/
高级特性.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
切片
已知 L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
如果说是取前三个元素的话,我们要怎么操作呢?
如果是c或者java写一个循环就可以了。但是python提供了更加简便的方法——切片
>>> L[0:3]
['Michael', 'Sarah', 'Tracy']
也可以
>>> L[:3]
['Michael', 'Sarah', 'Tracy']
之前我们谈论过,python的list列表里面的元素是镜像的,存在负参数
>>> L[-2:]
['Bob', 'Jack']
>>> L[-2:-1]
['Bob']
甚至什么都不写,只写[:]就可以原样复制一个list:(全部元素)
tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,
只是操作的结果仍是tuple
字符串'xxx'也可以看成是一种list,每个元素就是一个字符。因此,
字符串也可以用切片操作,只是操作结果仍是字符串:
>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[::2]
'ACEG'
迭代
如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,
这种遍历我们称为迭代(Iteration)。在Python中,迭代是通过for ... in来完成的,
而很多语言比如C语言,迭代list是通过下标完成的
list这种数据类型虽然有下标,但很多其他数据类型是没有下标的,但是,
只要是可迭代对象,无论有无下标,都可以迭代,比如dict就可以迭代
>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> for key in d:
... print(key)
...
a
c
b
默认情况下,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
for循环里,同时引用了两个变量,在Python里是很常见的,比如下面的代码:
>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
... print(x, y)
...
1 1
2 4
3 9
列表生成式
列表生成式即List Comprehensions,是python内置的非常强大的来创建list的生成式。
举个例子,要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用list(range(1, 11)):
但如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么做?
>>> L = []
>>> for x in range(1, 11):
... L.append(x * x)
...
>>> L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
不仅如此,for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:
>>> [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']
生成器
在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,
只要把一个列表生成式的[]改成(),就创建了一个generator:
>>> 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对象:
<generator object <genexpr> at 0x1022ef630>
我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last): #数组越界
File "<stdin>", line 1, in <module>
StopIteration
要理解generator的工作原理,它是在for循环的过程中不断计算出下一个元素,
并在适当的条件结束for循环。
generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,
直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
当然,上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,
因为generator也是可迭代对象:
具体可以用到的就是斐波拉契数列和杨辉三角等
迭代器
我们已经知道,可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
可以使用isinstance()判断一个对象是否是Iterable对象:
>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False
而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,
直到最后抛出StopIteration错误表示无法继续返回下一个值了。
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用isinstance()判断一个对象是否是Iterator对象:
>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
把list、dict、str等Iterable变成Iterator可以使用iter()函数:
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True
总结
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
集合数据类型如list、dict、str等是Iterable但不是Iterator,
不过可以通过iter()函数获得一个Iterator对象。
Python的for循环本质上就是通过不断调用next()函数实现的