解析式
解析式
列表解析
列表解析式是将一个列表(实际上适用于任何可迭代对象(iterable))转换成另一个列表的工具。在转换过程中,可以指定元素必须符合一定的条件,才能添加至新的列表中,这样每个元素都可以按需要进行转换。
-
列表解析返回的是列表, 列表的内容是表达式执行的结果
-
列表解析的精髓就在第一个的for循环,所以第一个必须是for循环语句
-
解析式速度更快
-
代码更简洁
-
可读性
实际使用
-
列表解析的一般形式和其等价形式
[expr for item in itratorable] ==>
ret = []
for item in itratorable
ret.append(item)
实际使用举例:
In [2]: [ x ** 0.5 for x in range(5)]
Out[2]: [0.0, 1.0, 1.4142135623730951, 1.7320508075688772, 2.0]
In [8]: lst = []
In [9]: for x in range(5):
...: lst.append(x ** 0.5)
In [10]: lst
Out[10]: [0.0, 1.0, 1.4142135623730951, 1.7320508075688772, 2.0]
-
带if语句的列表解析
[expr for item in iterable if cond] =>
ret = []
for item in iterable:
if cond:
ret.append(expr)
实际使用举例:
In [11]: [ x ** 0.5 for x in range(10) if x % 2 == 0]
Out[11]: [0.0, 1.4142135623730951, 2.0, 2.449489742783178, 2.8284271247461903]
In [12]: lst = []
In [13]: for i in range(10):
....: if i % 2 == 0:
....: lst.append(i ** 0.5)
In [14]: lst
Out[14]: [0.0, 1.4142135623730951, 2.0, 2.449489742783178, 2.8284271247461903]
带两个if语句的使用:
[expr for item in iterable if cond1 if cond2] =>
ret = []
for item in iterable:
if cond1:
if cond2:
ret.append(expr)
实际使用举例:
In [15]: [ x for x in range(20) if x % 2 ==1 if x < 10 ]
Out[15]: [1, 3, 5, 7, 9]
In [16]: lst = []
In [17]: for x in range(20):
....: if x % 2 ==1:
....: if x < 10:
....: lst.append(x)
In [18]: lst
Out[18]: [1, 3, 5, 7, 9]
-
两个for语句的列表解析
[expr for item1 in iterable1 for item2 in iterable2] =>
ret = []
for item1 in iterable1:
for item2 in iterable2:
ret.append(expr)
实际使用举例:
In [19]: [(x,y) for x in range(3) for y in range(2)]
Out[19]: [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]
In [20]: lst = []
In [25]: for x in range(3):
....: for y in range(2):
....: lst.append((x,y))
....:
In [26]: lst
Out[26]: [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]
在上面的使用中我们可以看到只要第一个是for语句剩下的语句可以是一个或多个if语句也可以是一个或多个for语句。总之合理的使用列表解析能够很好的提高代码的可读性,同时也能提高性能。
In [27]: [(x,y) for x in range(3) if x % 2 == 1 for y in range(2)]
Out[27]: [(1, 0), (1, 1)]
In [28]: lst = []
In [29]: for x in range(3):
....: if x % 2 == 1:
....: for y in range(2):
....: lst.append((x,y))
....:
In [30]: lst
Out[30]: [(1, 0), (1, 1)]
生成器解析
对生成器解析来说,只需要简单的把中括号换成小括号就可以了,而生成器解析式是按需计算的或者说延迟计算或者叫惰性求值。它和列表解析的语法很像,但是在大数据量处理时,生成器表达式的优势就体现出来了,因为它的内存使用方式更好,效率更高,它并不创建一个列表,只是返回一个生成器。当然,列表解析并不会被遗弃。
(expr for iter_var in iterable)
(expr for iter_var in iterable if cond_expr)
举例:
In [37]: def inc(x):
....: print('inc {0}'.format(x))
....: return x+1
....:
In [38]: (inc(x) for x in range(3))
Out[38]: <generator object <genexpr> at 0x7fc804c5e7d8>
In [39]: [inc(x) for x in range(3)]
inc 0
inc 1
inc 2
Out[39]: [1, 2, 3]
In [42]: g = (inc(x) for x in range(3))
In [43]: next(g)
inc 0
Out[43]: 1
In [44]: next(g)
inc 1
Out[44]: 2
In [45]: next(g)
inc 2
Out[45]: 3
-
使用生成器解析式时一点next的元素超出则报StopIteration的异常。
-
生成器解析式只能一步步的向后而不能任意跳转。
-
在列表解析中的元素是可以查看的而生成器只能通过next进行查看元素。
集合解析
-
集合解析把列表解析的中括号变成大括号,返回集合。
-
集合解析拥有集合的特性即:集合解析中的元素没有重复值、集合的元素必须是可哈希的否则报TypeError异常。
In [3]: s = {x for x in [2,3,4,5,3,4,2,7,8]}
In [4]: s
Out[4]: {2, 3, 4, 5, 7, 8}
字典解析
-
字典解析也是使用大括号包围,并且需要两个表达式,一个生成key, 一个生成value 两个表达式之间使用冒号分割,返回结果是字典。
-
key是可hash的。
-
相同的key之间后面的值会覆盖前面值。
In [12]: { str(x):y for x in range(5) for y in range(6)}
Out[12]: {'0': 5, '1': 5, '2': 5, '3': 5, '4': 5}
In [13]: set = {}
In [14]: for x in range(5):
....: for y in range(6):
....: set[str(x)]=y
....:
In [15]: set
Out[15]: {'0': 5, '1': 5, '2': 5, '3': 5, '4': 5}