目录
解析式的简单介绍列表解析式字典解析式集合解析式推导式:Comprehensions(又称解析式),是Python的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列的结构体。 共有三种推导,在Python2和3中都有支持: a. 列表解析 # Python2只有列表解析 b.生成器解析 # Python3特有 c. 集合解析 # Python3特有 d.字典解析 # Python3特有 解析式的作用: a. 修改可迭代对象 b. 过滤可迭代对象
列表解析的一般形式:
[expression for item in iterable] #[表达式 for 元素 可迭代对象]接下来看几个示例:
In[23]: [2 ** n for n in range(10)] Out[23]: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] In[24]: def inc(x): ...: return x + 1 ...: In[25]: [inc(x) for x in range(10)] Out[25]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] In[26]: [0 for x in range(10)] Out[26]: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] In[27]: def non_return(x): ...: pass ...: In[28]: [non_return(x) for x in range(10)] Out[28]: [None, None, None, None, None, None, None, None, None, None]列表解析式返回的结果是列表,列表的内容是表达式执行的结果。接着看例子:
In[13]: [x for x in range(10) if x % 2 == 0] Out[13]: [0, 2, 4, 6, 8] # 上面的语句等效于 ret = [] for x in range(10): if x % 2 == 0: ret.append(x)可以使用python的timeit来测试两种方式的执行效率。会发现列表解析的执行效率会好一些,优势显而易见。
#!/usr/bin/env python # -*- coding: utf-8 -*- # Created by Xi on 2019-02-21 import timeit list =[] def fun(): for i in range(100): if i%2==0: list.append(i) n =1000000 if __name__ == '__main__': print(timeit.timeit(stmt=fun,number=n)) print(timeit.timeit(stmt="[x for x in range(100) if x%2==0]",number=n))输出结果:
7.920102399999999 4.7217728999999995如果列表解析式中有if关键字呢:
[expression for item in iterable if condition] #[表达式 for 元素 in 可迭代对象 if 条件语句] # 等价于 ret = [] for item in iterable: if condition: ret.append(exper)以上介绍的只带了一个if关键字,如果有多个if关键字呢:
[experessi on for item in iterable if condition1 if condition2] # 等价于 ret = [] for item in iterable: if condition1: if condition2: ret.append(experession)针对上面来个例子:
[x for x in range(10) if x % 2 == 0 if x > 1] [2, 4, 6, 8] # 再来个例子 lst = [[0, 1], [1, 2], [2, 3], [3, 4], [4]] [x for x in lst if len(x) > 1 and x.pop(0) % 2 == 0]不但可以有多个if关键字,还可以有多个for关键字:
>>> [(x, y) for x in range(3) for y in range(3)] [(0, 0), (0, 1), (0, 2),1(, 0), (1, 1), (1, 2),(2, 0), (2, 1), (2, 2)]写成一个公式类的写法为:
[expr for item1 in iterable1 for item2 in iterable2] # 等价于 ret = [] for item1 in iterable1: for item2 in iterable2: ret.append(expr)那么for与if都有呢?多个for语句相当于逐层for嵌套。
# 逐层嵌套 In[11]: [(x, y) for x in range(5) for y in range(5) if (x+y) % 2 == 0] Out[11]: [(0, 0), (0, 2), (0, 4), (1, 1), (1, 3), (2, 0), (2, 2), (2, 4), (3, 1), (3, 3), (4, 0), (4, 2), (4, 4)] [(x, y) for x in range(10) if x % 2 == 0 for y in range(10)] # 等价于 ret = [] for x in range(10): if x % 2 == 0: for y in range(10): ret.append((x, y))如果for关键字不在第一个位置,会不会出问题呢?
In[12]: [x if True for x in range(10)] File "<ipython-input-12-c9daacf14b27>", line 1 [x if True for x in range(10)] ^ SyntaxError: invalid syntax因此,for关键字要写在前面,后面可以用for或if进行嵌套。
多看几个例子吧:
In[9]: [(x+1, x+2) for x in range(5)] Out[9]: [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)] In[10]: [{x+1:x+2} for x in range(5)] Out[10]: [{1: 2}, {2: 3}, {3: 4}, {4: 5}, {5: 6}]列表解析用于可迭代对象做过滤和转换,返回值是列表。
help(filter) filter(lambda x: x % 2 == 0, range(10)) list(filter(lambda x: x % 2 == 0, range(10))) help(map) list(map(lambda x: x+1, range(10))) [x+1 for x in range(10)] # Python里,可以不用filter及map函数,使用列表解析式可以秒杀filter及map # 上面的话并不是绝对的,当数据比较大时,使用filter及map将会比列表解析式快在Python中,lambda的语法是唯一的。其形式如下:
lambda argument_list: expression 其中,lambda是Python预留的关键字,argument_list和expression由用户自定义。这里的argument_list是参数列表。它的结构与Python中函数(function)的参数列表是一样的。 例如: lambda x, y: x*y; #函数输入是x和y,输出是它们的积x*y lambda:None; #函数没有输入参数,输出是None lambda *args: sum(args); #输入是任意个数的参数,输出是它们的和(隐性要求是输入参数必须能够进行加法运算) lambda **kwargs: 1; #输入是任意键值对参数,输出是1再来看一个例子,偶数求平方,奇数求立方。
lst = list(range(10)) [x ** 2 if x % 2 == 0 else x ** 3 for x in lst] #+RESULTS: | 0 | 1 | 4 | 27 | 16 | 125 | 36 | 343 | 64 | 729 |总结上述代码:
x if condition else y #当条件满足时返回x,当条件不满足时返回y。字典解析也需要一个大括号,并且要有两个表达式:一个生成key,一个生成value;两个表达式之间使用冒号分隔,返回结果是字典。示例:
print({str(x):x for x in range(10)}) {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}看一个例子:
{str(x):y for x in range(3) for y in range(4)} # 取决于短的那个 {'0': 3, '1': 3, '2': 3} #等价于 ret = {} for x in range(3): for y in range(4): ret[str(x)] = y print(ret)使用Markdown笔记本做的整理,跟咱们论坛的MD插件不是很兼容,格式有点混乱。兄弟们多包涵!