一、匿名函数
In [1]: def fn():
...: pass
...:
In [2]:
1、匿名函数 就是没有名字的函数,那么就用 lambda 这个关键字来定义
In [1]: lambda x: x + 1 # lambda 后面有一个参数x, 然后定义一个函数体, 冒号不换行
Out[1]: <function __main__.<lambda>>
In [2]: def fn(x):
...: return x + 1
...:
In [3]: (lambda x: x + 1)(3) # lambda x: x + 1 定义函数
Out[3]: 4
In [4]: fn(3)
Out[4]: 4
In [5]:
匿名函数的几个特点:
- 用lambda 关键字来定义
- 参数列表 不需要用 圆括号括起来
- 冒号 不是用来开启新的语句
- 最后一个表达式 没有return语句,最后一个表达式的值 就是我们的返回值
In [5]: f = fn(3)
In [6]: f
Out[6]: 4
In [7]: def counter():
...: c = 0
...: def inc():
...: nonlocal c
...: c += 1
...: return c
...: return inc
...:
In [8]: f = counter()
In [9]: f
Out[9]: <function __main__.counter.<locals>.inc>
In [10]: f()
Out[10]: 1
In [11]: counter()()
Out[11]: 1
In [12]: f = lambda x: x + 1
In [13]: f
Out[13]: <function __main__.<lambda>>
In [14]: f(3)
Out[14]: 4
In [15]: f = fn
In [16]: f(3)
Out[16]: 4
f = lambda x: if x < 0 : # 匿名函数只能写在一行里,因为只能写在一行里,所以 python中的匿名函数又称为 单行函数
0
else:
x
File "<ipython-input-35-dd0364e6568e>", 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]: 8
In [19]: (lambda x,y: x + y)(3, 5) # 多个 参数
Out[19]: 8
In [20]: def fn(x, y=3): # 默认 参数
...: return x + y
...:
In [21]: fn(3)
Out[21]: 6
In [22]: (lambda x,y=3: x + y)(3) # 默认 参数
Out[22]: 6
In [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]: True
In [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 参数
3
In [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 namedtuple
In [38]: User = namedtuple('u', ['name', 'age'])
In [39]: User
Out[39]: __main__.u
In [40]: users = [User('miracle', 18), User('chenyihan', 17), User('mage', 88)]
In [41]: users
Out[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].age
Out[43]: 18
In [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]: 88
In [46]: for user in users:
...: print(get_age(user))
...:
18
17
88
In [47]: lambda x: x.age
Out[47]: <function __main__.<lambda>>
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]: <map at 0x7fe8d451f668>
In [51]: list(map(lambda x: x.age, users))
Out[51]: [18, 17, 88]
In [52]: list(map(lambda x: x.name, users))
Out[52]: ['miracle', 'chenyihan', 'mage']
In [53]: names = []
In [54]: for user in users:
...: names.append(user.name)
...:
In [55]: map(lambda x: x.name, users)
Out[55]: <map at 0x7fe8d4534e10>
In [56]:
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]: r
Out[6]: <generator object g at 0x7fd943bd9c50>
In [7]: r.__iter__
Out[7]: <method-wrapper '__iter__' of generator object at 0x7fd943bd9c50>
In [8]: l = range(10)
In [9]: l.__iter__
Out[9]: <method-wrapper '__iter__' of range object at 0x7fd942fa5c00>
In [10]: i = iter(l)
In [11]: i.__next__
Out[11]: <method-wrapper '__next__' of range_iterator object at 0x7fd9439e4f00>
In [12]: next(i)
Out[12]: 0
In [13]: next(l)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-13-cdc8a39da60d> in <module>()
----> 1 next(l)
TypeError: 'range' object is not an iterator
In [14]: next(r)
Out[14]: 0
In [15]: next(r)
Out[15]: 1
In [16]: next(r)
Out[16]: 2
In [17]: next(r)
Out[17]: 3
In [18]: next(r)
Out[18]: 4
In [19]: for x in r:
...: print(x)
...:
5
6
7
8
9
In [20]: next(r)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-20-8ebe59a56b1d> in <module>()
----> 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]: g
Out[25]: <generator object gen at 0x7fd943bd9d58>
In [26]: next(g)
a
Out[26]: 1
In [27]: next(g)
b
Out[27]: 2
In [28]: next(g)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-28-e734f8aca5ac> in <module>()
----> 1 next(g)
StopIteration: 3
In [29]: next(g)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-29-e734f8aca5ac> in <module>()
----> 1 next(g)
StopIteration:
In [30]:
带 yield语句 的函数,称之为 生成器函数, 生成器函数的返回值是 生成器
gen(), 是 生成器函数
g = gen() , g 是 生成器
- 生成器函数 执行的时候,不会执行函数体(这里说的 生成器函数执行, 不是生成器执行的时候)
- 当next生成器的时候,当前代码会执行到之后的 第一个yield,弹出值,并暂停函数
- 当再次执行next 生成器的时候,从上次暂停的地方开始往下执行
- 当没有多余的yield 的时候,会抛出StopIteration 异常, 如果函数有返回值(return),异常的value 就是函数的返回值
In [31]: next(gen())
a
Out[31]: 1
In [32]: def gen(x):
...: if x == 0:
...: yield x
...:
In [33]: id(gen(0))
Out[33]: 140571121128288
In [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]: 1
In [39]: inc(c)
Out[39]: 2
In [40]: inc(c)
Out[40]: 3
In [41]: inc(c)
Out[41]: 4
In [42]: inc(c)
Out[42]: 5
In [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]: <function __main__.inc.<locals>.<lambda>>
In [51]: incr()
Out[51]: 1
In [52]: incr()
Out[52]: 2
In [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]: 1
In [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))
...:
70330367711422815821835254877183549770181269836358732742604905087154537118196933579742249494562611733487750449241765991088186363265450223647106012053374121273867339111198139373125598767690091902245245323403501
In [66]: def fn():
...: while True:
...: pass
...: for i in range(1000000):
...: yield i
...:
In [67]:
习题:
1. 实现一个扁平化字典
2. base64编码
3. 最长公共子串