「Lambda」Python中的匿名函数

最近深入研究了一下Python里匿名函数的作用,所以来记录一下。

你可能知道,从Java7到Java8发生了一个很大的变动,那就是增加了匿名函数。利用Java8中的匿名函数,你可以将函数直接赋值给一个变量。如果你需要实现一个只需要用到一次的接口,传统的Java7要求你必须定义一个“污染环境”的接口,而利用lambda,Java8就会干净许多。

再回到Python上来。首先,Python中lambda的格式是这样的:

lambda <参数>: <表达式>

表达式就是函数体。

参数和有名函数的规则是一样的,你同样可以通过a=1来赋默认值,也同样可以使用*args**kwargs

Python中的lambda其实并没有像Java中那样大的影响,因为,Python中,一般的有名函数也可以实现闭包,赋值给变量这些功能。lambda只是让你能够将函数嵌入到一行内,这就让你在编写一些功能简单,并且一次性的函数时,代码会简洁许多。给一个例子:

# 有名函数
def square(x):
    return x**2


squared = list(map(square, [1, 2, 3, 4, 5]))

但如果我们使用lambda,就会简洁很多:

# 匿名函数
squared = list(map(lambda x: x**2, [1, 2, 3, 4, 5]))

Python中的lambda也有很多限制,比如说函数体只能由一条表达式组成,这也就使得lambda不能实现一些复杂的功能。

切记,不要为了将代码压缩到一行而使用过于复杂的lambda嵌套,这样会使你的代码无法阅读。Python注重可读性,The Zen of Python中强调:

Flat is better than nested.

你的确可以用lambda将一个较为复杂的程序写成一行,比如,这是一个仅用一行完成的猜数游戏,长这样:

(lambda __builtin__: (lambda __print, __y, d: [(lambda ___: None)(d.guess_my_number(42)) for d.guess_my_number in [(lambda n:[(__y(lambda __this: (lambda d: (lambda __after: [(lambda __after: (lambda ___: __after(d))(__print('Not a positive integer!')) if (d.len(d.user_input)==0 or (not d.user_input.isdigit())) else [(lambda __after: (lambda ___: __after(d))(__print('Too big! Try again!')) if d.user_input>d.n else (lambda __after: (lambda ___: __after(d))(__print('Too small! Try again!')) if d.user_input<d.n else (lambda ___: d.True)(__print('You win!')))(lambda d: __after(d)))(lambda d: __after(d)) for d.user_input in [(d.int(d.user_input))]][0])(lambda d: __this(d)) for d.user_input in [(d.raw_input('Enter a positive integer to guess: '))]][0] if d.True else __after(d))(lambda d: None))))(d) for d.n in [(n)]][0])]][0])(__builtin__.__dict__['print'],(lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))),type('StateDict',(),__builtin__.__dict__)()))(__import__('__builtin__'))

我想这样你就会对嵌套后的lambda有多难阅读有个体会,这种代码看看玩就行。GitHub上面有一个库,可以帮助你将代码写到一行内

lambda与Python内置函数结合使用

lambda还可以与Python内置函数结合在一起使用,比如说我在举例说明lambda作用时使用的map()。

map()

Map会将一个函数映射到一个输入列表的所有元素上。换个说法,就是将列表中每个元素作为函数的输入值,然后将此元素更改为函数的输出值。

此时,lambda用于指定对每个元素的共同操作。

还是用开头的那个例子,使用map是这样写的:

squared = list(map(lambda x: x**2, [1, 2, 3, 4, 5]))
# result: [1, 4, 9, 16, 25]

不使用map就得用for循环:

items = [1, 2, 3, 4, 5]
squared = []
for i in items:
    squared.append(i**2)

你看,map是不是简单漂亮的多。

当然,这里注意一个点,在Python2中,map返回的是一个列表,而在Python3中,map返回的是迭代器,要想得到返回的列表,可以使用list,所以上面我也是这么做的。

filter()

顾名思义,filter就是过滤器。Filter会检查列表中的所有元素,并筛选出对前面函数能返回True的元素。

此时,lambda用于指定筛选条件。

举一个简单的例子:

less_than_zero = list(filter(lambda x: x < 0, range(-10, 10)))
# result: [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1]

同样要注意在Python3中返回值为迭代器的问题。

reduce()

Reduce用于将列表中相邻的两个元素依次结合在一起。

此时,lambda用于指定元素的结合方式。

同样,这里有一个例子:

product = reduce(lambda x, y: x*y, range(10))
# result: 3628800

这里需要注意的点是,在Python2中,reduce是内置函数,而在Python3中,你需要用from functools import reduce导入才可使用。

Ending

在最后,我还有一点要说的是,关于lambda,有两个极为nb的东西:

\[\lambda表达式(lambda\quad expression)\quad和\quad\lambda算法(lambda\quad caculus) \]

不过,对Python中的lambda而言,并不存在lambda expression和lambda caculus,所以,如果你看到别人在写关于Python lambda的文章时写到:

我使用的原理就是lambda caculus。

你大可无视掉。再次强调,Python中的lambda就是一个没有名字的、能够嵌入到一行内的函数

posted @ 2020-10-03 19:59  Liuxizai  阅读(54)  评论(0编辑  收藏