https://zhuanlan.zhihu.com/p/109084444
一 生成器
1. 生成器: 自定义迭代器
如何得到生成器:
在函数内, 一旦存在yield关键字, 调用函数并不会执行函数体代码, 而是会返回一个生成器对象, 生成器即自定义的迭代器.
def func(): print('第一次') yield 1 print('第二次') yield 2 print('第三次') yield 3 print('第四次') yield 4 g = func() print(g) # 结果: <generator object func at 0x0000026591539A98> i = g.__iter__() print(i) # 结果: <generator object func at 0x0000026591539A98> print(g.__next__()) # 会触发函数体代码的运行, 然后遇到yield停下来, 将yield后面的值当做本次next调用的结果返回 # 注意: g.__next__()等同于next(g) # yield可以返回一个值, 也可以返回多个值, 用逗号隔开. yield无值则返回None. 持续next, 如果没有yield, 则会报错. # 通常, yield与return并不会混用. # 生成器最大的优点是, 可以将函数挂起, 真正的应用场景在并发编程那里. # 应用案例: def my_range(start, end, step=1): while start < end: yield start start += step g = my_range(1, 10, 2) while True: try: print(next(g)) except StopIteration: break
2. 生成器的表达式形式
def dog(name): print('道哥%s准备吃东西啦'%name) while True: x = yield print('道哥%s吃了%s'%(name, x)) g = dog('egon') g.send(None) # 相当于next(g), 完成初始化 g.send('鸡肉') # 给yield传值, yield将值转交给x g.send('骨头') g.close() # g.send('米饭') # 关闭之后无法传值, 会报错
二 三元表达式
res = 值1 if 条件 else 值2
条件成立返回值1, 条件不成立返回值2.
def func(x, y): if x > y: return x else: return y res = func(1, 2) print(res) # 三元表达式 # 语法格式: 条件成立时要返回的值 if 条件 else 条件不成立时要返回的值 # 注意: 三元表达式可以用在函数内部 x = 1 y = 2 res = x if x > y else y print(res) res1 = x=1 if 1>2 else 3 print(res1) # 结果:3
三 生成式
l = [表达式 for x in 可迭代对象 if 条件]
dic = {k:v for k,v in 可迭代对象 if 条件}
set = {元素 for x in 可迭代对象 if 条件}
g = (表达式 for x in 可迭代对象 if 条件)
生成器表达式可以与sum, list等联用, 联用时可以去掉一个括号:
sum(表达式 for x in 可迭代对象 if 条件)
list(表达式 for x in 可迭代对象 if 条件)
1. 利用可迭代对象和for循环
2. 可以加if条件判断
1. 列表生成式
列表生成式是python为我们提供的一种简化代码的解决方案,用来快速生成列表,语法如下
[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)
lst = ['alex_dsb', 'lxx_dsb', 'wxx_dsb', 'egon'] new_lst = [] for name in lst: if name.endswith('dsb'): new_lst.append(name) print(new_lst) # 列表生成式 l = [name for name in lst if name.endswith('dsb')] print(l) # 结果: ['alex_dsb', 'lxx_dsb', 'wxx_dsb'] # 如果不加if判断, 则默认条件为True. # 如果条件判断非常复杂, 则没必要使用列表生成式, 因为使用列表生成式的目的是精简代码. # 示例: # 1. 将列表元素中所有小写字母变成大写 l1 = [name.upper() for name in lst] print(l1) # 结果: ['ALEX_DSB', 'LXX_DSB', 'WXX_DSB', 'EGON'] # 2. 所有名字去掉'_dsb' l2 = [name.replace('_dsb', '') for name in lst] print(l2) # 结果: ['alex', 'lxx', 'wxx', 'egon']
2. 字典生成式
# 1. 字典生成式 # 示例1: keys = ['name', 'age', 'gender'] dic = {key:None for key in keys} print(dic) # 结果: {'name': None, 'age': None, 'gender': None} # 示例2: items = [('name', 'egon'), ('age', 18), ('gender', 'male')] dic1 = {k:v for k,v in items if k != 'gender'} print(dic1) # 结果: {'name': 'egon', 'age': 18}
3. 集合生成式
# 集合生成式 info = ['name', 'age', 'gender'] set1 = {el for el in info} print(set1) # 结果: {'name', 'gender', 'age'}
4. 没有元祖生成式
元祖本身是不可变的数据类型, 当然也不可以添加
5. 生成器表达式
# 生成器表达式 g= (i for i in range(10) if i > 3) # 此刻, g内部没有存值 print(g) # 结果: <generator object <genexpr> at 0x000001C486FF9A98> print(next(g)) # 结果: 4 print(next(g)) # 结果: 5 print(next(g)) # 结果: 6 with open('a', mode='r', encoding='utf-8') as f: # 方式一: 节省内存空间 i = 0 for line in f: res = len(line.strip()) i += res print(i) # 方式二: 此方式节省内存空间 sum = 0 while True: try: res = next(f).strip() sum += len(res) except StopIteration: break print(sum) # 注意: sum中计算的应该是可迭代对象; next(f)取出的是一行的内容, 不是单个字符. # 方式三: 利用列表生成式和sum, 但是耗费内存空间 lst = [len(line.strip()) for line in f] res = sum(lst) print(res) # 方式四: 效率最高, 最节约空间 res = sum((len(line.strip()) for line in f)) print(res)
# 以上表达式可以简写为 res = sum(len(line.strip()) for line in f), 即去除生成器外面的括号