首页 > 代码库 > 解析式

解析式

解析式

列表解析

列表解析式是将一个列表(实际上适用于任何可迭代对象(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]: lstOut[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]: lstOut[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]: lstOut[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]: lstOut[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]: lstOut[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 0inc 1inc 2Out[39]: [1, 2, 3]In [42]: g =  (inc(x) for x in range(3))In [43]: next(g)inc 0Out[43]: 1In [44]: next(g)inc 1Out[44]: 2In [45]: next(g)inc 2Out[45]: 3
  • 使用生成器解析式时一点next的元素超出则报StopIteration的异常。

  • 生成器解析式只能一步步的向后而不能任意跳转。

  • 在列表解析中的元素是可以查看的而生成器只能通过next进行查看元素。

集合解析

  • 集合解析把列表解析的中括号变成大括号,返回集合。

  • 集合解析拥有集合的特性即:集合解析中的元素没有重复值、集合的元素必须是可哈希的否则报TypeError异常。

In [3]: s = {x for x in [2,3,4,5,3,4,2,7,8]}In [4]: sOut[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]: setOut[15]: {‘0‘: 5, ‘1‘: 5, ‘2‘: 5, ‘3‘: 5, ‘4‘: 5}

解析式