python中的 3元表达式是对 if...else... 语句的一种简写~;这个在不少时候都很是有用,并且能够使代码简单且易于维护。python
x = 3 y = 4 if x > y: res = x else: res = y
上述代码若使用 3元表达式,if...else...语句能够简写成一行express
x = 4 y = 3 res = x if x > y else y
上述例子中,3元表达式最左边的 x 和最右边的 y 能够写成任意的表达式app
x = 4 y = 3 res = 'aaa' if x > y else 'bbb'
列表解析(list comprehension),通常会配合 for 循环,以比较优雅的方式生成列表,大大减小代码量,且加强了代码的可读性~ide
s = [] for i in 'hello': s.append(i.upper()) print(s) 输出结果: ['H', 'E', 'L', 'L', 'O']
上述代码若使用列表解析,可以使用以下代码替换,输出结果一致:函数
s = [i.upper() for i in 'hello'] print(s)
说明:for 循环获得的每个元素返回给 for 前面的 i 变量,而后执行 upper 函数,将执行结果以列表的形式返回~。相比于 for 循环,列表解析的语法由 c语言实现,性能会有所提高~性能
列表解析中,for 循环后面亦可添加 条件语句,筛选出知足条件的元素:code
lst = [1,2,60,67,34,78,98,70,89] print([i for i in lst if i > 50]) 输出结果: [60, 67, 78, 98, 70, 89]
总结一下列表解析的语法:对象
[expression for item1 in iterable1 if condition1 for item2 in iterable2 if condition2 ..... for itemN in iterableN if conditionN ]
绝大多数的状况,列表解析仅使用一层循环,即:索引
[expression for item in iterable if condition]
上面已经给出列表解析的语法,for 循环前面的 expression 能够是一个变量,也能够是一个表达式,看以下示例,列表中的×××(int)原样取出,如果浮点类型(float),则进行四舍五入后取出:内存
a = [1,2,3.2,1.3,5.9] res = [i if isinstance(i, int) else int(round(i)) for i in a] res : [1, 2, 3, 1, 6]
这里 for 循环前的 expression 是一个三元表达式,判断语句在三元表达式中实现~
for 循环前的 expression 也能够是一个 常量,例如要获取一个固定长度的,且都是某个值的列表:
lst = [0 for i in range(10)] # 长度为10,全为0 的列表 lst : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
列表解析多层 for 循环示例,读取列表中每一个单词的字母,并生成一个新的列表:
lst = ['hello', 'kitty'] res = [l for word in lst for l in word] res : ['h', 'e', 'l', 'l', 'o', 'k', 'i', 't', 't', 'y']
如上示例可能一会儿难以理解,根据列表解析的语法:
[expression for item1 in iterable1 if condition1 for item2 in iterable2 if condition2 ..... for itemN in iterableN if conditionN ] 相似于 res=[] for item1 in iterable1: if condition1: for item2 in iterable2: if condition2: ...... for itemN in iterableN: if conditionN: res.append(expression)
如上示例使用 for 循环表示:
res = [] for word in lst: for l in word: res.append(l) print(res) 输出结果: ['h', 'e', 'l', 'l', 'o', 'k', 'i', 't', 't', 'y']
列表解析并无下降代码的可读性,且缩小了代码量、提高了性能,可是若其中出现多层 for 循环嵌套,可能会下降代码的可读性,不易于理解~
列表解析会一次性生成全部的数据到内存中,而后生成列表对象,这样不适用于迭代大量的数据。 而生成器表达式正好解决了这个问题~
生成器表达式的语法与列表解析的语法相似,即外面的中括号 换成括号便可:
语法: (expression for item1 in iterable1 if condition1 for item2 in iterable2 if condition2 ..... for itemN in iterableN if conditionN ) 示例: >>> g = (i for i in range(100)) >>> g <generator object <genexpr> at 0x00000288D8C9A308>
若使用生成器表达式,全部的数据不会一次性所有加载到内存中,而是按照从前向后的顺序,用到一个加载一个。当数据量比较大时,更节省内存~
import time start_time = time.time() g = (i for i in range(100000000)) stop_time = time.time() print('run time is %s' % (stop_time - start_time)) print(next(g)) print(next(g)) print(next(g)) 输出结果: run time is 0.0 # 获得生成器 g 的用时~ 0 1 2
一样的数据量使用列表解析,会消耗至关长的时间,如果再加几个0,程序可能就会卡住:
import time start_time = time.time() lst = [i for i in range(100000000)] stop_time = time.time() print('run time is %s' % (stop_time - start_time)) lst_iter = lst.__iter__() print(next(lst_iter)) print(next(lst_iter)) print(next(lst_iter)) 输出结果: run time is 5.407538890838623 # 生成列表的时长 0 1 2
固然生成器表达式也有缺点,因为生成器表达式返回的是一个生成器,因此若要迭代全部的元素,只能从前日后挨个迭代;而列表解析返回的是列表,能够根据索引当即返回指定位置的元素~
gen = (i for i in range(100)) # print(gen[10]) # 错误 lst = [i for i in range(100)] print(lst[10]) # 没有问题
.................^_^