【Python】推导式与生成器

python 推导式

推导式comprehensions(又称解析式)

(一)、列表推导式(list comprehension)

语法规范:

out_list = [ out_express for out_express in input_list if out_express_condition]

其中的 if 条件判断根据需要可有可无。

# 0 ~ 9 中的偶数
a = [i for i in range(10) if i % 2 == 0]
print(a)
# [0, 2, 4, 6, 8]

不使用列表推导式的一般用法:

a = []
for i in range(10):
    if i % 2 == 0:
        evens.append(i)
带嵌套循环的推导式

把一个矩阵(以列表为元素的列表)展平为一个列表。

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]
a = [i for row in matrix for i in row]
print(a)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

不使用列表推导式的一般用法:

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]
a = []
for row in matrix:
    for i in row:
        a.append(i)
print(a)

带嵌套循环的推导式的断行:

# a = [i for row in matrix for i in row]
a = [
    i
    for row in matrix
    for i in row
]
(二)、字典推导式(dict comprehensions)

我们看先来看使用字典推导式的基础模板:{ key:value for key,value in existing_data_structure }
这里和list有所不同,因位dict里面有两个关键的属性,key 和 value,但大同小异,我们现在的expression部分可以同时对 key 和 value 进行操作

mcase = {'a': 10,  'A': 7,'b': 34, 'Z': 3}
mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys()}
# {'a': 17, 'b': 34, 'z': 3}

进行断行:

mcase = {'a': 10,  'A': 7,'b': 34, 'Z': 3}
mcase_frequency = {
    k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0)
    for k in mcase.keys()
}
# {'a': 17, 'b': 34, 'z': 3}

不使用字典推导式的一般用法:

mcase = {'a': 10,  'A': 7,'b': 34, 'Z': 3}
mcase_frequency = {}
for  key in mcase.keys():
    mcase_frequency.setdefault(key, mcase.get(key.lower(), 0) + mcase.get(key.upper(), 0) )
print(mcase_frequency)
# {'a': 17, 'b': 34, 'z': 3}

#字典推导式还可以快速对换一个字典的键和值
#{v: k for k, v in some_dict.items()}

mcase = {'a': 10,  'A': 7,'b': 34, 'Z': 3}
mcase_frequency = {v:k for k, v in mcase.items()}
print(mcase_frequency)
# {10: 'a', 7: 'A', 34: 'b', 3: 'Z'}
(三)、集合推导式(set comprehensions)

它们跟列表推导式也是类似的。 唯一的区别在于它们使用大括号{}

注:
(1)可以使用大括号 { } 或者 set() 函数创建集合,
(2)创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
(3)集合推导式去除重复值

my_set = {i * i for i in [-1, 1, 2, -2, 3]}
print(my_set)  
# {1, 4, 9}

需要保持集合的特点:不能含有重复元素。

生成器(Generators)

以上介绍了 列表、字典、集合三个推导式。同样元组也有同样变化,但是称为生成器表达式

当序列过长, 而每次只需要获取一个元素时,应当考虑使用生成器表达式而不是列表解析。生成器表达式的语法和列表解析一样,只不过生成器表达式是被()括起来的,而不是[],如下:

(expr for iter_var in iterable) 
(expr for iter_var in iterable if cond_expr)
my_generator = (i for i in range(5))  # 返回一个生成器
print(my_generator)
#<generator object <genexpr> at 0x000002562ECC2120>
my_generator = (i for i in range(5))  # 返回一个生成器
for i in my_generator:
    print(i)
# 0 1 2 3 4

生成器表达式并不真正创建数字列表, 而是返回一个生成器,这个生成器在每次计算出一个条目后(调用的时候再计算),使用了“惰性计算”(lazy evaluation)

生成器与推导式的优缺点

1.列表推导式是将所有的值一次性加载到内存中

优点:
(1)如果生成列表的方式不太复杂,这是建议使用列表推导式,其内部是通过cpython来实现的较用for循环要快

(2)列表推导式可以遍历任意次

2.生成器是将列表推导式的[]改成() 或者 使用yield关键字编写

优点:不会将所有的值一次性加载到内存中,延迟计算,一次返回一个结果,它不会一次生成所有的结果,这对大数据量处理,非常有用

缺点:生成器只能遍历一次,即不能向前读取数据

# 如果生成列表的方式不太复杂,这是建议使用列表推导式,其内部是通过cpython来实现的比较用for循环要快
from time import perf_counter
from functools import wraps


def spend_time(func):
    @wraps(func)
    def decorate_func(*args,**kwargs):
        start = perf_counter()
        func()
        all = perf_counter()-start
        print(all)
    return decorate_func

@spend_time
def for_func():
    mylist=[]
    all = range(1000000)
    for i in all:
        mylist.append(i)

@spend_time
def list_finc():
    mylsit=[i for i in range(1000000)]

if __name__ == '__main__':
    for_func()
    list_finc()

结果为:

0.10319479999998293
0.06540830000085407

引用:
https://www.jianshu.com/p/70b8b6561935

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何为xl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值