Python学习笔记--解析式

it2022-05-05  146

解析式

前言列表解析式定义解析式变体三元表达式 生成器解析式集合解析字典解析小结

前言

一般认为的python解析器如下:

[for i in range(10)]

事实上,这只是其中的一种。 解析式这个大概念可以分为以下几种:

列表解析式生成器解析式集合解析式字典解析式

列表解析式

如下对一个列表里所有的数值求平方就是列表解析式:

>>> lst = list(range(10)) >>> ret = [] >>> for x in lst: ... ret.append(x ** 2) ... >>> ret [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> >>> ret = [x ** 2 for x in lst] >>> ret [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

定义

通用语法:[expr for e in iterator] 再这个表达式里面我们可以使用我们的元素,这样子的列表解析式和我们的for循环是等价的。

列表解析式的优点:

代码简洁,可读性高效率比普通的迭代稍高,但并不是数据量级上的,只是稍微有一点。

解析式变体

如下为带if语句的列表解析

>>> lst = list(range(10)) >>> ret = [] >>> for x in lst: ... if x % 2 == 0: ... ret.append(x) ... >>> ret [0, 2, 4, 6, 8]

相当于如下用解析式的方式:

>>> ret = [x for x in lst if x % 2 == 0] >>> ret [0, 2, 4, 6, 8]

这种解析式是可以多个if组合的

>>> ret = [x for x in lst if x > 0 if x < 5] >>> ret [1, 2, 3, 4]

若表达式里面需要有一个或的关系,可以如下:

>>> ret = [x for x in lst if x < 5 or x > 7 if x % 2 == 0] >>> ret [0, 2, 4, 8]

若是想要用and也是一样的。因此:带多个if语句的,都可以转化为常见的逻辑运算,所有一般来说不会带多个if语句。

ret = [x for x in lst if x > 0 if x < 5 if x % 2 == 0] #这两种是等价的。 for x in lst: if (x % 2 == 0) and (x > 0) and (x < 5): ret.append(x)

那如果想要用2个元素进行就可以使用元组的形式进行封装

>>> ret = [] >>> for x in range(3): ... for y in range(4,7): ... ret.append((x,y)) ... >>> ret [(0, 4), (0, 5), (0, 6), (1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6)] >>> ret = [(x, y) for x in range(3) for y in range(4,7)] >>> ret [(0, 4), (0, 5), (0, 6), (1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6)]

解析式是可以有多个for语句逐层嵌套的

>>> ret = [] >>> for x in range(3): ... if x > 1: ... for y in range(3): ... ret.append((x,y)) ... >>> ret [(2, 0), (2, 1), (2, 2)] #上下两者是等价的 >>> ret = [(x, y) for x in range(3) if x > 1 for y in range(3)] >>> ret [(2, 0), (2, 1), (2, 2)]

for里面套if,if里面套for也是可以的

使用列表解析是为了让代码更简洁。但是如果解析式过于繁琐的话还是用for循环比较好。

三元表达式

偶数求平方,奇数求立方:

>>> ret = [] >>> for x in lst: ... if x % 2 == 0: ... ret.append(x ** 2) ... else: ... ret.append(x ** 3) ... >>> ret [0, 1, 4, 27, 16, 125, 36, 343, 64, 729] #等价于: >>> ret = [] >>> if x % 2 == 0: ... ret = x ** 2 ... else: ... ret = x ** 3 ... >>> ret 729

语法:x if cond else y

当条件(cond)满足时,返回x当条件不满足时,返回y

这种表达式我们称为三元表达式,也称为三目表达式。 用解析式的方式:

>>> ret = [x ** 2 if x % 2 == 0 else x ** 3 for x in lst] >>> ret [0, 1, 4, 27, 16, 125, 36, 343, 64, 729]

没有else是不行的,三元表达式只能用双分支

生成器解析式

使用生成器解析式可以实现按需取值:

>>> ret = (x ** 2 for x in range(10)) >>> ret <generator object <genexpr> at 0x000002011175FC48> >>> next(ret) 0 >>> next(ret) 1

这样就可以通过使用next()的方式获取值。 列表解析中的中括号变成小括号,就称为生成器解析式了 生成器解析式返回的是一个生成器

生成器的优点:

不占内存惰性求值

看看表达式什么时候计算的呢?

>>> def fn(x): ... print('executed') ... return x ... >>> g = (fn(x) for x in range(10)) >>> next(g) executed 0 >>> next(g) executed 1

如上可知,每次再next调用的时候才会进行计算。 生成器解析式和列表解析式是一摸一样的,只是生成器解析式返回的结果是一个生成器。

生成器都是迭代器生成器是无法用下标访问的

因此可知:

我们明确知道需要用下标访问的时候,用列表解析,只需要对结果迭代的时候,无论如何优先使用生成解析器如果我们要用缓存的话,就不能用生成器解析,要用列表解析。

集合解析

>>> ret = {x for x in range(10)} >>> ret {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} >>> type(ret) <class 'set'>

所有的操作都和列表解析是一样的,只不过返回的是集合

字典解析

>>> s = {str(x):x for x in range(3)} >>> s {'0': 0, '1': 1, '2': 2}

如上为字典解析,将key和value之间用冒号分隔,其他还是一样的。

小结

解析式这一章由很多我没有接触过的东西,但是也不难理解,看起来复杂还是和前面所学的几种数据结构息息相关。把握好前面的内容也就不难去理解了。


最新回复(0)