生成器
1.yield
若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象
>>> def my_range(start,stop,step=1):
... print('start...')
... while start < stop:
... yield start
... start+=step
... print('end...')
>>> g=my_range(0,3)
>>> g
<generator object my_range at 0x104105678>
生成器内置有__iter__和__next__方法,所以生成器本身就是一个迭代器
>>> g.__iter__
<method-wrapper '__iter__' of generator object at 0x1037d2af0>
>>> g.__next__
<method-wrapper '__next__' of generator object at 0x1037d2af0>
因而我们可以用next(生成器)触发生成器所对应函数的执行,
>>> next(g) # 触发函数执行直到遇到yield则停止,将yield后的值返回,并在当前位置挂起函数
start...
0
>>> next(g) # 再次调用next(g),函数从上次暂停的位置继续执行,直到重新遇到yield...
1
>>> next(g) # 周而复始...
2
>>> next(g) # 触发函数执行没有遇到yield则无值返回,即取值完毕抛出异常结束迭代
end...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
在函数内可以采用表达式形式的yield
>>> def eater():
... print('Ready to eat')
... while True:
... food=yield
... print('get the food: %s, and start to eat' %food)
...
可以拿到函数的生成器对象持续为函数体send值,如下
>>> g=eater() # 得到生成器对象
>>> g
<generator object eater at 0x101b6e2b0>
>>> next(e) # 需要事先”初始化”一次,让函数挂起在food=yield,等待调用g.send()方法为其传值
Ready to eat
>>> g.send('包子')
get the food: 包子, and start to eat
>>> g.send('鸡腿')
get the food: 鸡腿, and start to eat
针对表达式形式的yield,生成器对象必须事先被初始化一次,让函数挂起在food=yield的位置,等待调用g.send()方法为函数体传值,g.send(None)等同于next(g)
def MyGenerator():
v = yield 1# yield:语句执行到yield就停止了 所以刚开始运行到这一句的时候v没有赋值为1,等到send(5)时(yield 1被视为传入的参数5) 此时这一句被执行,v=5
v=yield v
b=yield v
v=yield v
c=yield b
gen = MyGenerator()
print (next(gen))
print (gen.send(5))# v = yield 1 ->v = 5 ,先yield v,未执行v = 这里的赋值语句
print (gen.send(7))# v = yield v ->v = 7 ,先yield v,未执行b = 这里的赋值
print (gen.send(5))# b = yield v ->b = 5 ,yield v(=7) ,未执行v = 这里的赋值
print (gen.send(7))# v = yield v ->v = 7 ,yield b(=5) 结束
def consumer():#generator
r = ''
while True:
n = yield r#consumer通过yield拿到消息,处理,又通过yield把结果传回;
if not n:
return
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK'
def produce(c):
c.send(None)#首先调用c.send(None)启动生成器,yield一个''进去
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)#一旦生产了东西,通过c.send(n)切换到consumer执行;
print('[PRODUCER] Consumer return: %s' % r)#produce拿到consumer处理的结果,继续生产下一条消息;
c.close()#produce决定不生产了,通过c.close()关闭consumer,整个过程结束。
c = consumer()
produce(c)
# [PRODUCER] Producing 1...
# [CONSUMER] Consuming 1...
# [PRODUCER] Consumer return: 200 OK
# [PRODUCER] Producing 2...
# [CONSUMER] Consuming 2...
# [PRODUCER] Consumer return: 200 OK
# [PRODUCER] Producing 3...
# [CONSUMER] Consuming 3...
# [PRODUCER] Consumer return: 200 OK
# [PRODUCER] Producing 4...
# [CONSUMER] Consuming 4...
# [PRODUCER] Consumer return: 200 OK
# [PRODUCER] Producing 5...
# [CONSUMER] Consuming 5...
# [PRODUCER] Consumer return: 200 OK
2.三元表达式
针对以下需求
def func(x,y):
if x > y:
return x
else:
return y
res=func(1,2)
print(res)
#等效于
res=x if x > y else y
print(res)
3.列表生成式
l = ['alex_dsb', 'lxx_dsb', 'wxx_dsb', "xxq_dsb", 'egon']
new_l=[]
for name in l:
if name.endswith('dsb'):
new_l.append(name)
new_l=[name for name in l if name.endswith('dsb')]
new_l=[name for name in l]
print(new_l)
把所有小写字母全变成大写
new_l=[name.upper() for name in l]
print(new_l)
把所有的名字去掉后缀_dsb
new_l=[name.replace('_dsb','') for name in l]
print(new_l)
2、字典生成式
keys=['name','age','gender']
dic={key:None for key in keys}
print(dic)
items=[('name','egon'),('age',18),('gender','male')]
res={k:v for k,v in items if k != 'gender'}
print(res)
3、集合生成式
keys=['name','age','gender']
set1={key for key in keys}
print(set1,type(set1))
4.生成器表达式
创建一个生成器对象有两种方式,一种是调用带yield关键字的函数,另一种就是生成器表达式,与列表生成式的语法格式相同,只需要将[]换成(),即:
(expression for item in iterable if condition)
对比列表生成式返回的是一个列表,生成器表达式返回的是一个生成器对象
g=(i for i in range(10) if i > 3)
强调:此刻g内部一个值也没有
print(g,type(g))
print(g)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
with open('笔记.txt', mode='rt', encoding='utf-8') as f:
# 方式一:
# res=0
# for line in f:
# res+=len(line)
# print(res)
# 方式二:
# res=sum([len(line) for line in f])
# print(res)
# 方式三 :效率最高
# res = sum((len(line) for line in f))
# 上述可以简写为如下形式
res = sum(len(line) for line in f)
print(res)