生成器:
函数内部有 yield 关键字,该函数执行的结果就是生成器函数,yield后跟返回值,不跟是None
生成器本质就是迭代器
def foo();
print(‘start‘)
yield # yield ok #可跟返回值
print(‘end‘)
g=foo() # g 就是生成器
res=g.__next__() # next 执行一次
如上代码:
函数碰到return结束,这里的yield相当于return,后面没有跟返回值,返回None
同一个生成器的话,碰到yield 暂停,再次执行next时,继续向下执行,重新生成器的话就重新开始了
yield表达式形式:
def foo():
print(‘start‘)
while Ture:
x=yield #返回值的 None(没有值,没有意义)
print(x) # x 是 yiled给的值,x 没有值 是None
g=foo()
print(g)
next(g)
#######执行结果是生成器,也就是g, next(g)执行一次,打印 start , 碰到 yield 然后暂停,把返回值返回(None);
再next一下,从暂停位置进行,打印x,在进入循环,碰到yield 暂停,把返回值返回
X没有值就失去了表达式的意义,如何给 X 传值呢??
def foo():
print(‘start‘)
while Ture:
x=yield #返回值的 None(没有值,没有意义) # g.send(1)
print(x) # x 是 yiled给的值,x 没有值 是None
g=foo()
print(g)
next(g)
g.send(1)
#跟 next 效果一样,都是触发函数继续进行的功能,但是 send 还有一个传值的功能
运行: 第一次 next(g) 走到了 yield 的时候暂停;然后进行 g.send(1),走之前会从暂停位置把 1 传给 yiled ,然后 yield 把值赋值给 X,然后继续往下走
X有值了,然后打印 X;然后再循环到 yield ,这时候就不传值了(send就是在开始阶段传值,后面就只有 next的功能),是返回值,但是X是有值的
注意:生成器是表达式形式的话,必须先send (None),在send其他值,或者先next()一下,在进行send
意思是必须得先让其做一个初始化,让其走到一个暂停的位置,因为send是基于 yield 在暂停的情况来传值的
yield功能:
1.相当于把__iter__和__next__方法封装到函数里
2.与return的功能类似,但是return只能返回一次值,而yoeld可以返回多次
3.函数暂停与再继续的状态由yiled保存
就像linux中的管道 | ,可以隔离两边的命令,把左边的结果给右边
生成器模拟tail -f动态获取新增一行:
思路:
以读的模式打开一个文件,光标立马跑到最后,进入循环读的过程,读到值返回,没读到重新进入下一次循环
import time #导入time模块
def tail(filepath,encoding=‘utf-8‘): #定义函数 tail 传入filepath(文件路径)参数,并默认指定为 utf-8
with open(filepath,encoding=encoding) as f: #以读形式打开文件,赋值给 f(encoding等于默认的指定编码)
f.seek(0,2) # seek 控制光标到末尾,然后再进行读一行操作(以末尾为参照(0,2),光标跑到最后)
while True:
line=f.readline() # 读一行内容并赋值给 line ,光标移动到这一行的最后
if line: # if line 判断 line 是不是空的 如果是空的就是False 反之为 Ture
yield line # 返回 line
else:
time.sleep(0.5)
countue # 没有值的话延迟,再读一次 countue可不加
def grep(lines,pattern): # lines 就是tail执行的结果,pattern 是要过滤的内容
for line in lines: # 就是在for i in tail这个生成器(g),如下,把g1,g2当做参数传入grep,这里就是在循环g
if pattern in line:
print(line)
g1=tail(‘a.txt‘) # 用g 拿到生成器
g2=grep(g1,‘error‘)
g3=grep(g2,‘404‘)
for i in g3: #触发生成器的效果
print(i)
三元表达式:
条件成立返回的结果 条件 条件不成立返回的结果
如下:
x=2
y=3
if x > y:
print(x)
esle:
print(y)
精简为三元表达式: res= x if x>y else y res= ‘aaa‘ if x>y ‘666‘(两边是返回值,可以是任意的)
求最大值:
def max2(x,y):
if x>y:
return x
else:
return y
精简: return x if x>y else y
print(max2(4,6))
列表解析:
把字符串每个字符取出来大写,存成列表
s=‘hello‘
l=[]
for i in s:
res=i.upper()
l.append(res)
print(l)
列表解析:
s=‘hello‘
res=[i.upper() for i in s] #循环遍历 s 成立取出来的 i ,把 i 放到左边执行upper变大写,存入列表中
print(res)
把大于50的值取出来存入列表:
l=[1,31,73,84,57,22]
l_new=[]
for i in l:
if i>50:
l_new.append(i)
print(l_new)
列表解析:
l_new=[i for i in l if i>50] (这里不加else,因为不知道是if 的else 还是for 的else)
print(l_new)
生成器表达式:
与列表解析语法一样,但是得到的结果是生成器,别列表解析更省内存
l=[ i for i in range(10000000000000000000000000000000000000000000000)]
这样的话会全部出来,占用内存
g=(i for i in range(10000000000000000000000000000000000000000000000))
拿到的结果是一个生成器(生成器的内存地址)
next(g) 就相当于是 g.__next__() 取出一个值,不管多少值,一次只取一个,不会像列表那样撑内存
表达式形式生成器:
x=yield None
面向过程:
就像是流水线,分一个个的阶段,一整套流程
核心就是过程,过程就是流程,解决问题的步骤,一步步实现
优点:
思路清晰,把复杂的问题简单化,流程化
缺点:
中间有一个环节有问题,那么整体就会有问题