14 python的生成器和列表推导式

一、 列表推导式

列表推导式(list comprehension)是指循环创建列表.

for循环有非常广的应用场景,也可以用来创建一个列表,而列表推导式就相当于for循环创建列表的简化版.

# for循环
list_a = list()
for a in range(5):
    list_a.append(a)
print(list_a)		# [1,2,3,4]

# 列表推导式
list_b = [b for b in range(5)]
print(list_b)		# [1,2,3,4]

1. 列表推导式书写形式:

[表达式 for 变量 in 列表] 或者 [表达式 for 变量 in 列表 if 条件]

lst = ['jerry', 'tony', 'tom', 'mok', 'abcd']
r = [name for name in lst if len(name) > 3]
print(r)
# ['jerry', 'tony', 'abcd']

r = [name.capitalize() for name in lst if len(name) > 3]
print(r)
['Jerry', 'Tony', 'Abcd']

2.下面来看复杂点的列表推导式:

# in后面跟其他可迭代对象,如字符串
list_c = [7 * c for c in "python"]
print(list_c)
 
# 带if条件语句的列表推导式
list_d = [d for d in range(6) if d % 2 != 0]
print(list_d)
 
# 多个for循环
list_e = [(e, f * f) for e in range(3) for f in range(5, 15, 5)]
print(list_e)
 
# 嵌套列表推导式,多个并列条件
list_g = [[x for x in range(g - 3, g)] for g in range(22) if g % 3 == 0 and g != 0]
print(list_g)
  • 运行结果:
['ppppppp', 'yyyyyyy', 'ttttttt', 'hhhhhhh', 'ooooooo', 'nnnnnnn']
[1, 3, 5]
[(0, 25), (0, 100), (1, 25), (1, 100), (2, 25), (2, 100)]
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14], [15, 16, 17], [18, 19, 20]]

代码解释:

  1. 列表推导式会遍历后面的可迭代对象,然后按照for前的表达式进行运算,生成最终的列表.

  2. 如果有if条件语句,for遍历后紧跟着进行条件判断.

  3. 如果有多个for循环,则最终的数据数量为多个for循环的笛卡尔积.

  4. 可以进行嵌套的列表推导,与嵌套for循环的原理相同.

3、代码可读性

  • 对于不熟悉列表推导式的人来说,可以使用for循环来实现相同的功能,但是需要好几行代码,而列表推导式只需要一行代码.
  • 很多人会说代码简洁了但可读性降低了,其实不然,当我们对列表推导式熟悉(自己写几次就熟悉了),代码的功能一眼就能轻松地看出来,但是for循环代码基本不可能一眼看完.尤其当创建列表的for循环嵌套在业务逻辑的其他for循环里时,恰恰是使用列表推导式的可读性最高.
  • 同时,在Python3中列表推导式有自己的局部作用域,就像函数似的.表达式内部的变量和赋值只在局部起作用,表达式的上下文里的同名变量还可以被正常引用,局部变量并不会影响到它们.
  • 也就是说,列表推导不会有变量泄漏的问题,在列表推导中的赋值操作不可能会影响到列表推导上下文中的同名变量.
  • 当然,也不是所有场景都推荐使用列表推导式.比如说:如果列表推导的代码超过了两行,就要考虑改成用for循环了.超过了两行的列表推导式就真的没有可读性了.通常的原则是,只用列表推导来创建新的列表,并且尽量保持简短.
    以上内容参考了 CSDN Python碎片 的《Python列表推导式》

二、生成器

  • 在Python中有一边循环一边计算的机制,称之为生成器 generator
  • .如何创建生成器

1.定义生成器方式一:通过列表推导式创建

# 需求:得到一个0-10之内 分别和3想乘的列表
new_lst = [x * 3 for x in range(10)]		# 列表推导式
print(type(new_lst),new_lst)
# <class 'list'>    [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]

g = (x * 3 for x in range(10))				# 生成器
print(type(g),g)
# <class 'generator'>    <generator object <genexpr> at 0x0000000002699E60>

# 获得元素方式一:生成器.__next__() 
print(g.__next__())         # 0
print(g.__next__())         # 3
print(g.__next__())         # 6
print(g.__next__())         # 9

# 获得元素方式二:next(生成器)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
# print(next(g)) # StopIteration 

2.定义生成器方式二:通过函数来完成

  • 只要在函数中添加了yield关键字,就变成了一个生成器函数
    • 1 .定义一个函数,函数中使用yield关键字
    • 2 .调用函数,接收调用结果
    • 3 .得到的结果就是个生成器
    • 4 .通过next()函数或__next__()获取元素
def fn():
    n = 0
    while True:
        n += 1
        # print(n)
        yield n  #  return n + 暂停
        # return n
n = fn()
print(n)
print(next(n))
print(next(n))

3.生成器元素获取方式

3.1 获得元素方式一:生成器.next()

3.2获得元素方式二:next(生成器)

3.3 使用注意事项

  • next取值时,不能超出生成器范围,否则会报错:StopIteration

4. yield 与 return的区别

  • return一般在函数中只设置一个,他的作用是终止函数,并且给函数的执行者返回值。

  • yield在生成器函数中可设置多个,他并不会终止函数,next会获取对应yield生成的元素。

更多生成器内容可参考: CSDN 爱咋闹 的《python之生成器的初识》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值