Python——各种推导式
列表推导式
-
格式:
列表推导式格式为:[表达式 for 变量 in 列表] [out_exp_res for out_exp in input_list] 或者 [表达式 for 变量 in 列表 if 条件] [out_exp_res for out_exp in input_list if condition]
- out_exp_res:列表生成元素表达式,可以是有返回值的函数。
- for out_exp in input_list:迭代 input_list 将 out_exp 传入到 out_exp_res 表达式中。
- if condition:条件语句,可以过滤列表中不符合条件的值。
-
示例:
过滤掉长度小于或等于3的字符串列表,并将剩下的转换成大写字母:>>> names = ['Bob','Tom','alice','Jerry','Wendy','Smith'] >>> new_names = [name.upper() for name in names if len(name)>3] >>> print(new_names) ['ALICE', 'JERRY', 'WENDY', 'SMITH']
计算 30 以内可以被 3 整除的整数:
>>> multiples = [i for i in range(30) if i % 3 == 0] >>> print(multiples) [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
字典推导式
-
格式:
字典推导基本格式:{ key_expr: value_expr for value in collection } 或 { key_expr: value_expr for value in collection if condition }
-
示例:
使用字符串及其长度创建字典:listdemo = ['Google','Runoob', 'Taobao'] # 将列表中各字符串值为键,各字符串的长度为值,组成键值对 >>> newdict = {key:len(key) for key in listdemo} >>> newdict {'Google': 6, 'Runoob': 6, 'Taobao': 6}
提供三个数字,以三个数字为键,三个数字的平方为值来创建字典:
>>> dic = {x: x**2 for x in (2, 4, 6)} >>> dic {2: 4, 4: 16, 6: 36} >>> type(dic) <class 'dict'>
元组推导式(生成器)
-
格式:
元组推导式的基本格式:(expression for item in Sequence ) 或 (expression for item in Sequence if conditional )
元组推导式和列表推导式的用法也完全相同,只是元组推导式是用
()
圆括号将各部分括起来,而列表推导式用的是中括号[]
,另外元组推导式返回的结果是一个生成器对象。 -
示例:
我们可以使用下面的代码生成一个包含数字 1~9 的元组:>>> a = (x for x in range(1,10)) >>> a <generator object <genexpr> at 0x7faf6ee20a50> # 返回的是生成器对象 >>> tuple(a) # 使用 tuple() 函数,可以直接将生成器对象转换成元组 (1, 2, 3, 4, 5, 6, 7, 8, 9)
-
注意
在 Python 中,生成器是一种特殊的可迭代对象,它会延迟加载元素,直到被请求才会加载。这在处理大量数据时会非常高效,它能提升存储效率。相比之下,list 对象为了方便计数和索引,一次性创建所有的元素。所以跟生成器相比,在元素个数相同时,list 需要占用更多内存。- 示例:
-
我们要计算前一百万个数字的平方和。如果使用 list 来实现,方法如下。
>>> # 创建列表对象 squares >>> squares = [x*x for x in range(10_000_000)] >>> # 计算它们的总和 >>> sum(squares) 333333283333335000000 >>> squares.__sizeof__() 81528032
如上所示,list 对象占据 81528032 字节。我们考虑使用 generator 进行相同的操作,代码如下。
>>> # 创建 generator 对象,保存每个数的平方数 >>> squares_gen = (x*x for x in range(10_000_000)) >>> # 计算它们的总和 >>> sum(squares_gen) 333333283333335000000 >>> squares_gen.__sizeof__() 96
使用generator与list 相比,前者的内存开销小得多,只有 96 字节。原因很简单,它不需要获取所有的元素。相反,它只需要获取各个元素在序列中的位置,创建下一个元素并呈现它,而且不必保存在内存中。
-
- 示例:
集合推导式
-
格式:
集合推导式基本格式:{ expression for item in Sequence } 或 { expression for item in Sequence if conditional }
-
示例:
计算数字 1,2,3 的平方数:>>> setnew = {i**2 for i in (1,2,3)} >>> setnew {1, 4, 9}
判断不是 abc 的字母并输出:
>>> a = {x for x in 'abracadabra' if x not in 'abc'} >>> a {'d', 'r'} >>> type(a) <class 'set'>
函数推导式
- 格式:
如果推导条件或者表达式特别复杂怎么办?可以使用函数。
把推导的条件放在函数中,既可以应对复杂的条件,又可以利用推导式的简洁写法。
同理,如果生成推导结果的过程很复杂,也可以把逻辑放到函数中。 - 示例:
-
推导所有1-100之间的所有质数:2,3,5,7…
def is_prime(num): if num == 1: return False for i in range(2, num): if (num % i) == 0: return False else: return True p_nums = [i for i in range(1, 100) if is_prime(i)] print(p_nums)
-
推导1900到2021年之间所有的年份,标记出闰年,生成结果:
def is_run(year): if (year % 4) == 0: if (year % 100) == 0: if (year % 400) == 0: return True # 整百年能被400整除的是闰年 else: return False else: return True # 非整百年能被4整除的为闰年 else: return False ryears = [f'闰{y}' if is_run(y) else y for y in range(1900, 2021)] print(ryears)
-
嵌套推导式(不推荐)
-
示例:
从2000年到2021年,生成每个月份:‘2000年:1月’, ‘2000年:2月’, ‘2020年:3月’, …, ‘2021年:12月’monthes = [f'{y}年:{m}月' for y in range(2000, 2022) for m in range(1,13) ]
这里有两个for循环,类似于:
monthes = [] for y in range(2000, 2022): for m in range(1, 13): monthes.append(f'{y}年:{m}月')
是不是下面的特别容易懂?所以两层的循环不推荐使用推导式
大数据量推导式
-
示例:
推导出1到100亿之间的数字的平方,代码如下:nums = [i * i for i in range(1, 10000000000)]
但是这段代码很可能会卡死你的电脑,除非你的电脑是超级计算机。因为它要在内存中做100亿次计算,然后保存这100亿个数字。
解决办法:-
使用生成器
把方括号改成圆括号就可以了nums = (i * i for i in range(1, 10000000000)) print(nums) print(next(nums)) print(next(nums)) print(next(nums)) <generator object <genexpr> at 0x7fa0b422feb0> 1 4 9
-