一、匿名函数
In [1]: def fn(): ...: pass ...: In [2]:
1、匿名函数 就是没有名字的函数,那么就用 lambda 这个关键字来定义
In [1]: lambda x: x + 1 # lambda 后面有一个参数x, 然后定义一个函数体, 冒号不换行 Out[1]:>In [2]: def fn(x): ...: return x + 1 ...: In [3]: (lambda x: x + 1)(3) # lambda x: x + 1 定义函数Out[3]: 4In [4]: fn(3)Out[4]: 4In [5]:
匿名函数的几个特点:
- 用lambda 关键字来定义
- 参数列表 不需要用 圆括号括起来
- 冒号 不是用来开启新的语句
- 最后一个表达式 没有return语句,最后一个表达式的值 就是我们的返回值
In [5]: f = fn(3)In [6]: fOut[6]: 4In [7]: def counter(): ...: c = 0 ...: def inc(): ...: nonlocal c ...: c += 1 ...: return c ...: return inc ...: In [8]: f = counter()In [9]: fOut[9]:.inc>In [10]: f()Out[10]: 1In [11]: counter()()Out[11]: 1In [12]: f = lambda x: x + 1In [13]: fOut[13]: >In [14]: f(3)Out[14]: 4In [15]: f = fnIn [16]: f(3)Out[16]: 4
f = lambda x: if x < 0 : # 匿名函数只能写在一行里,因为只能写在一行里,所以 python中的匿名函数又称为 单行函数 0 else: xFile "", line 1 f = lambda x: if x < 0 : # 匿名函数只能写在一行里,因为只能写在一行里,所以 python中的匿名函数又称为 单行函数 ^SyntaxError: invalid syntax
In [17]: def fn(x, y): ...: return x + y ...: In [18]: fn(3, 5)Out[18]: 8In [19]: (lambda x,y: x + y)(3, 5) # 多个 参数Out[19]: 8In [20]: def fn(x, y=3): # 默认 参数 ...: return x + y ...: In [21]: fn(3)Out[21]: 6In [22]: (lambda x,y=3: x + y)(3) # 默认 参数Out[22]: 6In [23]:
In [23]: def fn(*args): ...: print(args) ...: In [24]: fn(*range(3))(0, 1, 2)In [25]: (lambda *args: print(args))(*range(3)) # 可变参数(0, 1, 2)In [26]:
In [26]: def fn(*args, **kwargs): ...: print(args) ...: print(kwargs) ...: In [27]: (1, 2, 3)Out[27]: (1, 2, 3)In [28]: {'1': 1, '2': 2, '3': 3}Out[28]: {'1': 1, '2': 2, '3': 3}In [29]: {str(x): x for x in range(1, 4)} == {'1':1, '2': 2, '3': 3}Out[29]: TrueIn [30]: d = {'1': 1, '2': 2, '3': 3}In [31]: fn(**d)(){'1': 1, '2': 2, '3': 3}In [33]: (lambda *args, **kwargs: print(args, kwargs))(*range(1, 4), **{str(x): x for x in range(1, 4)}) # 可变参数+参数解构+字典解析(1, 2, 3) {'1': 1, '2': 2, '3': 3} # 可变参数+参数解构+字典解析In [34]: (lambda **kwargs: print(kwargs))(a=1){'a': 1}In [35]:
- int 类型 不能作为 关键字参数
- 可变关键字参数, 需要使用 字典 传入
- 参数解构 是需要 有两个星号**, 而不是传入字典
In [35]: (lambda *, x: print(x))(x=3) # keyeord-only 参数3In [36]:
2、匿名函数支持 所有的 参数类型
1)sorted
In [36]: 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 [37]: from collections import namedtupleIn [38]: User = namedtuple('u', ['name', 'age'])In [39]: UserOut[39]: __main__.uIn [40]: users = [User('miracle', 18), User('chenyihan', 17), User('mage', 88)]In [41]: usersOut[41]: [u(name='miracle', age=18), u(name='chenyihan', age=17), u(name='mage', age=88)]In [42]: def get_age(user): ...: return user.age ...: In [43]: users[0].ageOut[43]: 18In [44]: sorted(users, key=get_age)Out[44]: [u(name='chenyihan', age=17), u(name='miracle', age=18), u(name='mage', age=88)]In [45]: get_age(users[2])Out[45]: 88In [46]: for user in users: ...: print(get_age(user)) ...: 181788In [47]: lambda x: x.ageOut[47]:>In [48]: sorted(users, key=lambda x: x.age)Out[48]: [u(name='chenyihan', age=17), u(name='miracle', age=18), u(name='mage', age=88)]In [49]:
2)map
In [49]: help(map)help on class map in module builtins:class map(object) | map(func, *iterables) --> map object | | Make an iterator that computes the function using arguments from | each of the iterables. Stops when the shortest iterable is exhausted. | | Methods defined here: | | __getattribute__(self, name, /) | Return getattr(self, name). | | __iter__(self, /) | Implement iter(self). | | __new__(*args, **kwargs) from builtins.type | Create and return a new object. See help(type) for accurate signature. | | __next__(self, /) | Implement next(self). | | __reduce__(...) | Return state information for pickling.~(END)
In [50]: map(lambda x: x.age, users)Out[50]:
3)filter
In [56]: help(filter)Help on class filter in module builtins:class filter(object) | filter(function or None, iterable) --> filter object | | Return an iterator yielding those items of iterable for which function(item) | is true. If function is None, return the items that are true. | | Methods defined here: | | __getattribute__(self, name, /) | Return getattr(self, name). | | __iter__(self, /) | Implement iter(self). | | __new__(*args, **kwargs) from builtins.type | Create and return a new object. See help(type) for accurate signature. | | __next__(self, /) | Implement next(self). | | __reduce__(...) | Return state information for pickling.~(END)
In [57]: list(filter(lambda x: x.age < 30, users))Out[57]: [u(name='miracle', age=18), u(name='chenyihan', age=17)]In [58]: In [58]: ret = []In [59]: for user in users: ...: if user.age < 30: ...: ret.append(user) ...: In [60]: [user for user in users if user.age < 30]Out[60]: [u(name='miracle', age=18), u(name='chenyihan', age=17)]In [61]:
二、生成器
In [4]: def g(): ...: for x in range(10): ...: yield x # 弹出一个值 ...: In [5]: r = g()In [6]: rOut[6]:In [7]: r.__iter__Out[7]: In [8]: l = range(10)In [9]: l.__iter__Out[9]: In [10]: i = iter(l)In [11]: i.__next__Out[11]: In [12]: next(i)Out[12]: 0In [13]: next(l)---------------------------------------------------------------------------TypeError Traceback (most recent call last) in ()----> 1 next(l)TypeError: 'range' object is not an iteratorIn [14]: next(r)Out[14]: 0In [15]: next(r)Out[15]: 1In [16]: next(r)Out[16]: 2In [17]: next(r)Out[17]: 3In [18]: next(r)Out[18]: 4In [19]: for x in r: ...: print(x) ...: 56789In [20]: next(r)---------------------------------------------------------------------------StopIteration Traceback (most recent call last) in ()----> 1 next(r)StopIteration: In [21]:
In [23]: def gen(): ...: print('a') ...: yield 1 ...: print('b') ...: yield 2 ...: return 3 ...: In [24]: g = gen()In [25]: gOut[25]:In [26]: next(g)aOut[26]: 1In [27]: next(g)bOut[27]: 2In [28]: next(g)---------------------------------------------------------------------------StopIteration Traceback (most recent call last) in ()----> 1 next(g)StopIteration: 3In [29]: next(g)---------------------------------------------------------------------------StopIteration Traceback (most recent call last) in ()----> 1 next(g)StopIteration: In [30]:
带 yield语句 的函数,称之为 生成器函数, 生成器函数的返回值是 生成器
gen(), 是 生成器函数
g = gen() , g 是 生成器
- 生成器函数 执行的时候,不会执行函数体(这里说的 生成器函数执行, 不是生成器执行的时候)
- 当next生成器的时候,当前代码会执行到之后的 第一个yield,弹出值,并暂停函数
- 当再次执行next 生成器的时候,从上次暂停的地方开始往下执行
- 当没有多余的yield 的时候,会抛出StopIteration 异常, 如果函数有返回值(return),异常的value 就是函数的返回值
In [31]: next(gen())aOut[31]: 1In [32]: def gen(x): ...: if x == 0: ...: yield x ...: In [33]: id(gen(0))Out[33]: 140571121128288In [34]: def counter(): ...: x = 0 ...: while True: ...: x += 1 ...: yield x ...: In [35]: def inc(c): ...: return next(c) ...: In [36]: def _counter(): ...: c = 0 ...: def inc(): ...: nonlocal c ...: c += 1 ...: return c ...: return inc ...: In [37]: c = counter()In [38]: inc(c)Out[38]: 1In [39]: inc(c)Out[39]: 2In [40]: inc(c)Out[40]: 3In [41]: inc(c)Out[41]: 4In [42]: inc(c)Out[42]: 5In [43]: inc(c)Out[43]: 6...In [48]: def inc(): ...: c = counter() ...: return lambda: next(c) ...: In [49]: incr = inc()In [50]: inc()Out[50]:. >In [51]: incr()Out[51]: 1In [52]: incr()Out[52]: 2In [53]: incr()Out[53]: 3
加上了lambda 之后,inc()变成了 生成器函数了
incr 才是生成器
In [55]: def inc(): ...: def counter(): ...: x = 0 ...: while True: ...: x += 1 ...: yield x ...: c = counter() ...: return lambda: next(c) ...: In [56]: incr = inc()In [57]: incr()Out[57]: 1...In [59]: def make_inc(): ...: def counter(): ...: x = 0 ...: while True: ...: x += 1 ...: yield x ...: c = counter() ...: return next(c) ...: In [60]: make_inc()Out[60]: 1In [61]:
- 用了一个无限大的列表来不断的计数下去
- 并没有全局变量
- 对于counter 来说,就是一个闭包
- c 就是一个counter 的实例
- 在最后return 的这个匿名函数,每次执行都是引用这个生成器
In [62]: def fib(n): ...: if n == 0: ...: return 1 ...: if n == 1: ...: return 1 ...: return fib(n-1) + fib(n-2) ...: In [63]: def _fib(): ...: a = 0 ...: b = 1 ...: while True: ...: a, b = b, a+b ...: yield a ...: In [64]: f = _fib()In [65]: for _ in range(1000): ...: next(f) ...: print(next(f)) ...: 70330367711422815821835254877183549770181269836358732742604905087154537118196933579742249494562611733487750449241765991088186363265450223647106012053374121273867339111198139373125598767690091902245245323403501In [66]: def fn(): ...: while True: ...: pass ...: for i in range(1000000): ...: yield i ...: In [67]:
习题:
1. 实现一个扁平化字典
2. base64编码
3. 最长公共子串