匿名函数 lambda
什么是匿名函数呢:匿名函数即是没有名字的函数。
匿名函数的定义:使用lambda关键字来定义匿名函数,参数列表不需要小括号,冒号是用来分割参数列表和表达式的,不需要再使用return语句,冒号右边就是函数的返回值,lambda表达式(匿名函数)只能写在一行上。被称为单行函数,lambda的主要用途在于高阶函数传参数时,使用lambda可以写出更简单的代码,简化代码
lambda匿名函数最好使用在只传一个参数的时候,函数比较简单
格式 : lambda 参数列表 :表达式
匿名函数举例:
lambda x : x **2 #这里是定义匿名函数
(lambda x : x **2)(4) #这里是调用匿名函数 并传入一个值给x 为4
print((lambda x, y=3: x + y)(5, 6))
print((lambda *args: (x for x in args))(*range(5)))
[x for x in (lambda *args: map(lambda x: x+1, args))(*range(5))] #高阶函数
[x for x in (lambda *args: map(lambda x: (x+1,args), args))(*range(5))]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
生成器函数
生成器generator:生成器指的是生成器对象,可以由生成器表达式得到,也可以使用yield关键字得到一个生成器函数,调用这个函数就可以得到一个生成器对象。
生成器函数:只要函数体中包含了yield语句的函数,那么这个函数就是生成器函数,调用后返回一个生产器对象,生成器对象就是一个可迭代对象,是一个迭代器,生成器对象是延迟计算的,惰性求值
**生成器函数包含yield语句的生成器函数调用生成生成器对象的时候,生成器函数的函数体不会立即执行next(generator)会从函数的当前位置向后执行到之后碰到的第一个yield语句,会弹出值,并暂停函数执行再次调用next函数,和上一条一样的处理过程继续调用next函数,生成器函数如果结束执行了(显式或隐式调用了return语句),会抛出StopIteration异常
生成器函数调用:普通的函数调用fn(),函数会立即执行完毕,但是生成器函数可以使用next函数多次执行生成器函数等价于生成器表达式,只不过生成器函数可以写得更加的复杂
生成器函数yield举例:
def inc():
for i in range(5):
yield i # 这里有yield 这个函数就是生成器函数
print(type(inc))print(type(inc()))
x = inc() # 这里调用函数
print(type(x))
print(next(x)) # 这里像函数要一个返回值 返回一个
for m in x: # 这里遍历生成器生成的生成器对象
print(m, '*')
for m in x:
print(m, '**')
yield 使用:
举例:
def gen():
print('line 1 ')
yield 1 #使用next()执行到这里会停一下返回值
print('line 2 ')
yield 2 ##使用next()执行到这里会停一下返回值
print('line 3 ')
retun 3 # 到return函数结束 不会再执行yield
yield
在生成器函数中,使用多个yield语句,执行一次后会暂停执行,
把yield表达式的值返回再次执行会执行到下一个yield语句return语句依止函数运行,
但return语句的返回值不能被获取到return会导致当前函数返回,无法继续执行,也无法继续获取下一个值,抛出StopIteration异常
如果函数没有显式的return语句,如果生成器函数执行到结尾(相当于执行了return None),一样会抛出StopIteration异常
生成器的应用
无限循环
def counter():
i = 0
while True:
i += 1
yield i #用yield来隔离 要一次执行一次 不会出现无线循环 倒置电脑死机
definc(c):
return next(c)c= counter()print(inc(c))print(inc(c))
计数器
def inc():
def counter():
i = 0
while True:
i += 1
yield i #yield 不怕死机
c = counter()
return lambda : next(c) #这里是返回了一个匿名函数lambda并且用next()拨动了一下counter函数
foo= inc() #把生成器函数给foo
print(foo()) #执行foo
print(foo()) #执行foo得到的结果是不一样的 因为没有重新运行函数
生成器的应用2:协程coroutine
生成器的高级用法
比进程、线程轻量级
是在用户空间调度函数的一种实现
Python3 asyncio就是协程实现,已经加入到标准库
Python3.5使用async、await关键字直接原生支持协程
协程调度器实现思路
有2个生成器A、B
next(A)后,A执行到了yield语句暂停,然后去执行next(B),B执行到yield语句也 暂停,然
后再次调用next(A),再调用next(B)在,周而复始,就实现了调度的效果
可以引入调度的策略来实现切换的方式
协程是一种非抢占式调度
def inc(): def inc():
for x in range(1000): yield from range(1000) # 与左边等价 函数结果是一样的 左边的简写方式
yield x #生成器函数
yield from是Python 3.3出现的新的语法
yield from iterable是for item in iterable: yield item形式的语法糖
从可迭代对象中一个个拿元素
def counter(n): #生成器,迭代器
for x in range(n):
yield x
def inc(n):
yield from counter(n)
foo = inc(10)
print(next(foo))
print(next(foo))