一、匿名函数
1、定义
语法格式:
lambda args:expression
args:以逗号分隔的参数列表
expression:用到args中各参数的表达式
lambda定义的代码必须是合法的表达式,不能出现多条件语句(可使用if的三元表达式)和非表达式,如for和while等
lambda的首要用途是指定短小的回调函数
lambda将返回一个函数而不是将函数赋值给某变量名
In [77]: lambda x: x+1 Out[77]: <function __main__.<lambda>> In [78]: f = lambda x: x+1 In [79]: type(f) Out[79]: function In [80]: f(1) Out[80]: 2 In [81]: f(2) Out[81]: 3 # 也可以直接使用小括号也调用匿名函数 In [88]: lambda x: x+1 Out[88]: <function __main__.<lambda>> In [89]: (lambda x: x+1) Out[89]: <function __main__.<lambda>> In [90]: (lambda x: x+1)(3) # 第一个小括号用来改变优先级,第二个表示调用函数 Out[90]: 4
总结:
匿名函数使用lambda定义, lambda是一个表达式而非语句
匿名函数(lambda表达式)只能写在一行上,所有也有人叫它单行函数
lamdba是一个单个表达式,而不是一个代码块
参数列表不需要使用小括号
冒号不是用来开启新的语句块,而是分隔参数列表和表达式
没有return语句,最后一个表达式的值即为返回值
def语句创建的函数将赋值给某变量名,而lambda表达式直接返回函数
lambda也支持使用默认参数,关键字参数,可变参数,参数解构
In [130]: (lambda : 0)() Out[130]: 0 In [131]: (lambda x: 0)(1) Out[131]: 0 In [132]: (lambda x, y: x+y)(3, 5) Out[132]: 8 In [133]: (lambda *args, **kwargs: print(args, kwargs)) (*range(3), **{str(x):x for x in range(3)}) (0, 1, 2) {'0': 0, '1': 1, '2': 2}
匿名函数常用于高阶函数中参数传递参数(当此函数参数非常短小时)
In [136]: help(sorted) Help on built-in function sorted in module builtins: sorted(iterable, /, *, key=None, reverse=False) Return a new list containing all items from the iterable in ascending order. A custom key function can be supplied to customize the sort order, and the reverse flag can be set to request the result in descending order. (END) In [146]: lst = [1, 3, 5, 7, 2, 4, 6, 8] In [146]: lst = [1, 3, 5, 7, 2, 4, 6, 8] In [147]: sorted(lst) Out[147]: [1, 2, 3, 4, 5, 6, 7, 8] In [148]: sorted(lst, reverse=True) Out[148]: [8, 7, 6, 5, 4, 3, 2, 1] In [149]: lst == [1, 3, 5, "x", "xxj", "j", 2] Out[149]: False In [150]: lst = [1, 3, 5, "x", "xxj", "j", 2] In [151]: sorted(lst) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-151-904d7ad462e2> in <module>() ----> 1 sorted(lst) TypeError: '<' not supported between instances of 'str' and 'int' In [152]: lst.sort() --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-152-e0fe8579802d> in <module>() ----> 1 lst.sort() TypeError: '<' not supported between instances of 'str' and 'int'
二、生成器
1、生成器函数
In [161]: def g(): ...: for x in range(10): ...: yield x # 表示弹出一个值 ...: In [162]: r =g In [163]: type(r) Out[163]: function In [164]: r = g() # 此时函数已经执行完成了,函数讲道理已经被销毁了;但事实上没有被销毁 这是生成器函数和普通函数的区别 In [165]: type(r) Out[165]: generator In [166]: r Out[166]: <generator object g at 0x7f7c20cdc938> In [161]: def g(): ...: for x in range(10): ...: yield x ...: In [169]: next(r) Out[169]: 0 In [170]: next(r) Out[170]: 1 In [171]: next(r) Out[171]: 2 In [172]: next(r) Out[172]: 3
生成器函数的工作过程:
In [174]: def gen(): ...: print('a') ...: yield 1 ...: print('b') ...: yield 2 ...: print('c') ...: return 3 ...: In [175]: g = gen() In [176]: g Out[176]: <generator object gen at 0x7f7c20cdc620> In [177]: next(g) a Out[177]: 1 In [178]: next(g) b Out[178]: 2 In [185]: def gen(): ...: print('a') ...: yield 1 ...: print('b') ...: yield 2 ...: print('c') ...: return 3 ...: In [186]: g = gen() # 执行生成器函数的时候,函数体并没有被执行 In [187]: g Out[187]: <generator object gen at 0x7f7c2025f938> In [188]: next(g) # 第一个next时,执行到第一个yield,停止执行 a Out[188]: 1 In [189]: next(g) # 第2个next时,从第1个yield之后开始执行到第2个yield,停止执行 b Out[189]: 2 In [190]: next(g) # 第3次next时,从第2个yield之后开始执行,当没有更多yield时,抛出 StopIteration,异常的值是函数的返回值 c --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-190-5f315c5de15b> in <module>() ----> 1 next(g) StopIteration: 3 In [197]: next(g) --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-197-5f315c5de15b> in <module>() ----> 1 next(g) StopIteration: In [193]: def gen(): ...: print('a') ...: yield 1 ...: print('b') ...: yield 2 ...: print('c') ...: In [194]: g = gen() In [195]: next(g) a Out[195]: 1 In [196]: next(g) b Out[196]: 2 In [197]: next(g) c --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-197-5f315c5de15b> in <module>() ----> 1 next(g) StopIteration: # 生成器函数没有返回值时,StopIteration也没有值
总结:
带yield语句的函数称之为生成器函数,生成器函数的返回值是生成器
生成器是特殊的迭代器
生成器函数执行的时候,不会执行函数体
当next生成器的时候,当前代码执行到第一个yield,会弹出值,并暂停函数
当再次next生成器时,从上次暂停处开始往下执行到下一个yield
当没有多余的yield的时候,会抛出StopIteration异常,异常的Value是函数的返回值
生成器是惰性求值的
可用于作计数器:
In [7]: def counter(): ...: x = 0 ...: while True: ...: x += 1 ...: yield x ...: In [8]: def inc(): ...: c = counter() ...: return lambda: next(c) ...: In [9]: g = inc() In [10]: g() Out[10]: 1 In [11]: g() Out[11]: 2 In [12]: g() Out[12]: 3
节省内存:
In [14]: def bib(): ...: a = 0 ...: b = 1 ...: while True: ...: a, b = b, a+b ...: yield a ...: In [15]: g = bib() In [16]: g Out[16]: <generator object bib at 0x7fb26f6bf990> In [17]: next(g) Out[17]: 1 In [18]: next(g) Out[18]: 1 In [19]: next(g) Out[19]: 2 In [20]: next(g) Out[20]: 3 In [21]: next(g) Out[21]: 5
协程 -- 生成器的高级用法
协程运行在一个线程内,在用户态调度;也被称为轻量线程
调度就是由调度器来决定哪段代码占用CPU时间
由系统内核调度的是内核态调度
用户自己写代码实现调度器来调度是用户态调度
非抢占式调度