解析式
In [2]: lst = list(range(10))
In [3]: ret = []
In [4]: for x in lst:
...: ret.append(x ** 2)
...:
In [5]: ret
Out[5]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
In [6]: ret = [x ** 2 for x in lst]
In [7]: ret
Out[7]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
In [8]:
一、列表解析式
语法:[expr for e in iterator]
优点:
- 代码简洁,可读性强
- 效率比 普通迭代稍高, 并不是数量级的提升
In [8]: %%timeit
...: lst = list(range(100000))
...: ret = []
...: for x in lst:
...: ret.append(x ** 2)
...:
34.9 ms ± 421 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [9]: %%timeit
...: lst = list(range(100000))
...: ret = [x ** 2 for x in lst]
...:
29.6 ms ± 341 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [10]:
In [10]: ret = []
In [11]: for x in lst:
...: if x % 2 == 0:
...: ret.append(x)
...:
In [12]: ret
Out[12]: [0, 2, 4, 6, 8]
In [13]: ret = [x for x in lst if x > 0 and x < 5]
In [14]: ret
Out[14]: [1, 2, 3, 4]
In [15]:
In [15]: ret = [x for x in lst if x < 5 or x > 7 if x % 2 == 0]
In [16]: ret
Out[16]: [0, 2, 4, 8]
In [17]:
In [18]: [(x, y) for x in range(5) for y in range(5, 10)]
Out[18]:
[(0, 5),
(0, 6),
(0, 7),
(0, 8),
(0, 9),
(1, 5),
(1, 6),
(1, 7),
(1, 8),
(1, 9),
(2, 5),
(2, 6),
(2, 7),
(2, 8),
(2, 9),
(3, 5),
(3, 6),
(3, 7),
(3, 8),
(3, 9),
(4, 5),
(4, 6),
(4, 7),
(4, 8),
(4, 9)]
In [19]:
In [19]: ret = []
In [20]: for x in range(5):
...: for y in range(5, 10):
...: ret.append((x, y))
...:
In [21]: ret
Out[21]:
[(0, 5),
(0, 6),
(0, 7),
(0, 8),
(0, 9),
(1, 5),
(1, 6),
(1, 7),
(1, 8),
(1, 9),
(2, 5),
(2, 6),
(2, 7),
(2, 8),
(2, 9),
(3, 5),
(3, 6),
(3, 7),
(3, 8),
(3, 9),
(4, 5),
(4, 6),
(4, 7),
(4, 8),
(4, 9)]
In [22]:
ret = []
for x in range(5):
for y in range(5, 10):
for z in range(10, 15):
In [23]: ret = [(x, y, z) for x in range(5) for y in range(5, 10) for z in range(10, 15)]
In [24]: ret
Out[24]:
[(0, 5, 10),
(0, 5, 11),
(0, 5, 12),
(0, 5, 13),
(0, 5, 14),
(0, 6, 10),
(0, 6, 11),
(0, 6, 12),
(0, 6, 13),
(0, 6, 14),
(0, 7, 10),
(0, 7, 11),
(0, 7, 12),
(0, 7, 13),
(0, 7, 14),
(0, 8, 10),
(0, 8, 11),
(0, 8, 12),
(0, 8, 13),
(0, 8, 14),
(0, 9, 10),
(0, 9, 11),
(0, 9, 12),
(0, 9, 13),
(0, 9, 14),
(1, 5, 10),
(1, 5, 11),
(1, 5, 12),
(1, 5, 13),
(1, 5, 14),
(1, 6, 10),
(1, 6, 11),
(1, 6, 12),
(1, 6, 13),
(1, 6, 14),
(1, 7, 10),
(1, 7, 11),
(1, 7, 12),
(1, 7, 13),
(1, 7, 14),
(1, 8, 10),
(1, 8, 11),
(1, 8, 12),
(1, 8, 13),
(1, 8, 14),
(1, 9, 10),
(1, 9, 11),
(1, 9, 12),
(1, 9, 13),
(1, 9, 14),
(2, 5, 10),
(2, 5, 11),
(2, 5, 12),
(2, 5, 13),
(2, 5, 14),
(2, 6, 10),
(2, 6, 11),
(2, 6, 12),
(2, 6, 13),
(2, 6, 14),
(2, 7, 10),
(2, 7, 11),
(2, 7, 12),
(2, 7, 13),
(2, 7, 14),
(2, 8, 10),
(2, 8, 11),
(2, 8, 12),
(2, 8, 13),
(2, 8, 14),
(2, 9, 10),
(2, 9, 11),
(2, 9, 12),
(2, 9, 13),
(2, 9, 14),
(3, 5, 10),
(3, 5, 11),
(3, 5, 12),
(3, 5, 13),
(3, 5, 14),
(3, 6, 10),
(3, 6, 11),
(3, 6, 12),
(3, 6, 13),
(3, 6, 14),
(3, 7, 10),
(3, 7, 11),
(3, 7, 12),
(3, 7, 13),
(3, 7, 14),
(3, 8, 10),
(3, 8, 11),
(3, 8, 12),
(3, 8, 13),
(3, 8, 14),
(3, 9, 10),
(3, 9, 11),
(3, 9, 12),
(3, 9, 13),
(3, 9, 14),
(4, 5, 10),
(4, 5, 11),
(4, 5, 12),
(4, 5, 13),
(4, 5, 14),
(4, 6, 10),
(4, 6, 11),
(4, 6, 12),
(4, 6, 13),
(4, 6, 14),
(4, 7, 10),
(4, 7, 11),
(4, 7, 12),
(4, 7, 13),
(4, 7, 14),
(4, 8, 10),
(4, 8, 11),
(4, 8, 12),
(4, 8, 13),
(4, 8, 14),
(4, 9, 10),
(4, 9, 11),
(4, 9, 12),
(4, 9, 13),
(4, 9, 14)]
In [25]:
什么时候用列表解析式?
- 跟着感觉走
- 太复杂,需要转换的,就写for循环
- 多个for循环,明显不知道结果是什么的,就不要用了
- 一眼看不出解析式的结果是什么,也不要用了
# 偶数求平方, 奇数求立方
In [27]: ret = []
In [28]: for x in lst:
...: if x % 2 == 0:
...: ret.append(x ** 2)
...: else:
...: ret.append(x ** 3)
...:
In [29]: ret
Out[29]: [0, 1, 4, 27, 16, 125, 36, 343, 64, 729]
In [30]:
In [30]: ret = x ** 2 if x * 2 == 0 else x ** 3 # 三元表达式, 三目表达式
# 语法: ret = x if cond else y
# 偶数求平方, 奇数求立方
In [33]: ret = []
In [34]: for x in lst:
...: ret = [x ** 2 if x % 2 == 0 else x ** 3 for x in lst]
...:
In [35]: ret
Out[35]: [0, 1, 4, 27, 16, 125, 36, 343, 64, 729]
In [36]:
In [37]: 3 if True else 4
Out[37]: 3
In [38]: 3 if True # Python中 三元表达式, 必须要有else,且只能有一个 if... else
File "<ipython-input-38-20b69ec8c953>", line 1
3 if True
^
SyntaxError: invalid syntax
In [39]:
二、生成器解析式
In [40]: g = (x ** 2 for x in range(100)) # 使用一对圆括号 代替之前的 方括号,这就变成了 生成器解析式
In [41]: g
Out[41]: <generator object <genexpr> at 0x7f1935b64a98>
In [42]:
生成器解析式,返回的是一个生成器
优点: 不占内存, 惰性求值
In [42]: def fn(x):
...: print('executed')
...: return x
...: g = (fn(x) for x in range(10))
...:
In [43]:
什么时候使用生成器?
- 明确知道使用下标的时候,用列表解析式,因为生成器是无法使用下标进行访问的
- 如果我们用缓存,就不能用生成器解析式了,就要用列表解析式了
三、集合解析式
In [46]: { x for x in range(10)} # 使用 {} 替换之前的 方括号
Out[46]: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
In [47]: s = {x for x in range(10)} # 返回的是一个 set
In [48]: type(s)
Out[48]: set
In [49]:
四、字典解析
In [50]: {str(x): x for x in range(10)} # key 和 value 之间需要用 冒号 进行分割。
Out[50]:
{'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9}
In [51]: d = {}
In [52]: for x in range(10):
...: d[str(x)] = x
...:
In [53]: d
Out[53]:
{'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9}
In [54]: {str(x): x ** 2 for x in range(10)}
Out[54]:
{'0': 0,
'1': 1,
'2': 4,
'3': 9,
'4': 16,
'5': 25,
'6': 36,
'7': 49,
'8': 64,
'9': 81}
可迭代对象 和 迭代器
In [55]: r = range(10)
In [56]: r.__iter__
Out[56]: <method-wrapper '__iter__' of range object at 0x7f1934f28810>
In [57]: s = '123'
In [58]: s.__iter__
Out[58]: <method-wrapper '__iter__' of str object at 0x7f1934e503e8>
In [59]: i = 1
In [60]: i.__iter__
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-60-c79eb23e70cf> in <module>()
----> 1 i.__iter__
AttributeError: 'int' object has no attribute '__iter__'
In [61]:
有__iter__方法的对象叫做 可迭代对象。
In [62]: for x in range(10):
...: pass
...:
In [63]: b = b'abc'
In [64]: b[0]
Out[64]: 97
In [65]:
哪些数据结构是可迭代对象:
- list
- set
- tuple
- dict
- str
- bytearray
- bytes
迭代器是可迭代对象, 可迭代对象不一定是迭代器
In [68]: it = iter(range(10)) # 我们可以通过 iter() 将可将迭代对象转换为 迭代器
In [69]: it.__next__()
Out[69]: 0
In [70]: it.__next__()
Out[70]: 1
In [71]: it.__iter__
Out[71]: <method-wrapper '__iter__' of range_iterator object at 0x7f1935968ea0>
In [72]:
有__next__方法的,我们称为 迭代器
In [72]: lst = [['m', 1, 2, 3, 4], ['age', 1, 2, 3]]
In [73]: for x in lst:
...: key = x[0]
...: for v in x[1:]:
...: print(v)
...:
1
2
3
4
1
2
3
In [74]: for x in lst:
...: it = iter(x)
...: key = next(it)
...: for v in it:
...: print(v)
...:
1
2
3
4
1
2
3
In [75]:
for in 循环对于可迭代对象:
- 首先调用 iter 方法转化为迭代器
- 然后不断的调用next方法
- 直接抛出 StopIteration异常
it = iter(iterable)
while True:
try:
next(it)
except StopIteration:
return
作业:
- 1. 把字符串形式的整数或浮点数转化为int 或者float,**不是int 和 float 函数**
提示: 可以使用字典
- 2. 移出列表中的重复元素,并保持新列表和原列表的顺序一致
- 3. 统计文本中各单词出现的次数
- 4. 把1-4000 之间的任意整数转化为罗马数字