一、基础复习
- 函数的基本用法 创建和调用函数 函数的形参与实参等等
- 函数的几种参数 位置参数、关键字参数、默认参数等
- 函数的收集参数*args **args 解包参数详解
- 函数中参数的作用域 局部作用域 全局作用域 global语句 嵌套函数 nonlocal语句等详解
- 函数的闭包(工厂函数)
二、函数lambda表达式
1.lambda表达式
lambda函数也叫匿名函数,即没有名字的函数。lambda函数没有名字。
基本语法为:
lambda [arg1 [,arg2,…argn]]:expression
lambda函数中冒号:左边为输入的参数,右边为输出及返回值。
举例如下:
>>> a=lambda x,y : x*y
>>> a(2,4)
8
>>>
2.lambda与函数的应用
优点:lambda是一个表达式而非语句,所以它能出现在python语法不允许def语句出现的地方。
缺点:所有的功能代码都局限在一个表达式中去实现,因此lambda通常也只能实现那些较为简单的需求。
语法:
def < lambda >(arg1,arg2,arg3,...argN):
return expression
举例如下:
例1:求传入参数的平方值
# 普通函数写法
>>> def square(x):
return x*x
>>> square(3)
9
# lambda函数写法
>>> squareY=lambda y:y*y
>>> squareY(3)
9
>>>
>>> square # 一个函数的引用
<function square at 0x0000019CA3588048>
>>> squareY #整个表达式是一个函数的引用
<function <lambda> at 0x0000019CA141C1E0>
>>>
例2:lambda函数放到列表里面
代码注释:
y[0]相当于函数的引用, y[ 0 ]( [ 1 ])意思是把y的第二个元素2作为参数传进了这个lambda表达式
>>> y=[lambda x : x * x , 2 , 3]
>>> y[0] #整个表达式是一个函数的引用
<function <lambda> at 0x0000019CA3591620>
>>> y[0](y[1]) # y[1]结果作为实参,赋值到y[0]中。
4
>>> y[0](y[2])
9
>>>
3.map()、filter()函数和lambda()函数联用
map()函数和filter()函数,它们的参数都是要求传入一个用于计算的函数
比如map()函数,它的第一个参数就是一个函数的引用,剩下的参数是要求序列类型,然后把每个元素挨个传递给第一个参数指定的函数,然后在运算之后把他们的结果构成一个迭代器。
map(function, iterable, …)
- function 指定一个函数
- iterable 指定一个可迭代对象
- 省略号 … 还可以继续指定多个可迭代对象,前提是函数要支持相应数量的参数
map()函数用法如下:
>>> # 将 "FishC" 转换成对应的 Unicode 编码
>>> mapped = map(ord, "FishC")
>>> list(mapped)
[70, 105, 115, 104, 67]
>>> # 下面代码相当于 [pow(2, 5), pow(3, 2), pow(10, 3)]
>>> list(map(pow, [2, 3, 10], [5, 2, 3])) #第一个列表中迭代选2,第二个列表中迭代选5,依次进行计算
[32, 9, 1000]
>>> # 下面代码相当于 [max(1, 2, 0), max(3, 2, 3), max(5, 2, 9)]
>>> list(map(max, [1, 3, 5], [2, 2, 2], [0, 3, 9, 8]))
[2, 3, 9]
例3:map()和lambda()函数联用
代码注释:
把FishC的每一个字符转换成它的unicode编码,然后再把编码值加10给返回。
>>> mapped=map(lambda x : ord(x)+10, "FishC")
>>> list(mapped)
[80, 115, 125, 114, 77]
例3.1 普通函数的写法
>>> def boring(x):
return ord(x)+10
>>> list(map(boring,"FishC"))
[80, 115, 125, 114, 77]
>>>
例4 普通函数的写法-----filter()函数和lambda()函数联用
filter()函数: filter() 函数会根据提供的函数对指定的可迭代对象的每个元素进行运算,并将运算结果为真的元素,以迭代器的形式返回(注意:返回的是元素本身)。
如果提供的函数是 None,则会假设它是一个 “鉴真” 函数,即可迭代对象中所有值为假的元素会被移除。
filter(function, iterable) 相当于以下两个生成器表达式
- 当 function 参数不是 None 的时候相当于 (item for item in iterable if function(item));
- 当 function 是 None 的时候为 (item for item in iterable if item)。
返回值:以迭代器的形式返回运算结果为真的值。
基本用法:
>>> list(filter(None, [True, False, 1, 0]))
[True, 1]
>>> list(filter(str.islower, "FishC"))
['i', 's', 'h']
例4.1 filter()函数和lambda()函数联用
代码注释:
0为False其余为True,如果为0,就是false,相当于不成立。所以0到9十个数,分别模2等于0等都会被过滤出去,留下的都是奇数。
>>> list(filter(lambda x : x % 2,range(10)))
[1, 3, 5, 7, 9]
>>>
课后题:
1.请问下面代码会返回 True 还是 False 呢?
>>> def squareX(x):
... return x * x
...
>>> squareY = lambda y : y * y
>>> squareX == squareY
# 请问这里返回 True 还是 False
>>> squareX(3) == squareY(3)
# 请问这里返回 True 还是 False
答:第一个是返回 False;第二个是返回 True。
解析:squareX 返回的是函数对象,squareY 返回的是 lambda 函数对象;但它们执行的结果是一样的,都是计算参数的平方。
2.小甲鱼在视频中说,“由于lambda是一个表达式,因此它可以用在常规函数不可能存在的地方,比如把它放到列表里面……”,那么请问下面代码是否可以成功访问?
>>> def squareX(x):
... return x * x
...
>>> y = [squareX, 2, 3]
>>> y[0](y[1])
答:可以的。
解析:这里说常规函数不可能存在的地方(例如列表中),指的其实是整个函数的定义过程。
如果像下面这么写就不行了:
>>> y = [def squareX(x): return x * x, 2, 3]
SyntaxError: invalid syntax
3.请使用 map() 函数以下代码实现相同的功能?
>>> [x ** 2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
答:
>>> list(map((lambda x : x ** 2), range(10)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
解析:map() 函数会根据提供的函数对指定的可迭代对象的每个元素进行运算,并将返回运算结果以迭代器的形式返回。
那么这个指向的函数,我们就可以将它替换成 lambda 表达式的形式。
4.请使用 filter() 函数实现相同功能?
>>> [x for x in range(10) if x % 2]
[1, 3, 5, 7, 9]
答:
>>> list(filter((lambda x : x % 2), range(10)))
[1, 3, 5, 7, 9]
解析:filter() 函数函数会根据提供的函数对指定的可迭代对象的每个元素进行运算,并将运算结果为真的元素,以迭代器的形式返回(注意:返回的是元素本身)。
那么这个指向的函数,我们也同样可以将它替换成 lambda 表达式的形式。
5.请将下面的闭包函数成 lambda 表达式的实现形式?
>>> def power(exp):
... def exp_of(base):
... return base ** exp
... return exp_of
...
>>> square = power(2)
>>> cube = power(3)
>>> square(2)
4
>>> square(5)
25
>>> cube(2)
8
>>> cube(5)
125
答:
>>> f = lambda exp : lambda base : base ** exp
>>> square = f(2)
>>> square(5)
25
>>> cube = f(3)
>>> cube(2)
8
>>> cube(5)
125
解析:还是那句话,不管最后的 lambda 表达式多么复杂,“冒号的左侧是参数右侧是返回值“ 这个事实都不会改变!
6.请将下面三个装饰器函数写成 lambda 表达式的实现形式?
def add(func):
def inner():
x = func()
return x + 1
return inner
def cube(func):
def inner():
x = func()
return x * x * x
return inner
def square(func):
def inner():
x = func()
return x * x
return inner
@add
@cube
@square
def test():
return 2
print(test())
答:
@lambda func : lambda : func() + 1
@lambda func : lambda : func() * func() * func()
@lambda func : lambda : func() * func()
def test():
return 2
print(test())
解析:
因为装饰器只不过是一个语法糖,说白了就是 Python 在背后进行机械替换而已(这有点类似于 C 语言的宏定义)。
所以,这里我们将装饰器函数替换成 lambda 表达式,只要符合语法规范,也未尝不可实现~
题目来自小甲鱼python函数(VII)