Python定义匿名函数,以及如何捕获变量值?
定义匿名函数问题
你想为sort()操作创建一个很短的回调函数,但又不想用def去写一个单行函数,而是希望通过某个快捷方式以内联方式来创建这个函数。解决方案
当一些函数很简单,仅仅只是计算一个表达式的值的时候,就可以使用lambda表达式来代替了。比如:addlambdax,y:xyadd(2,3)5add(hello,world)helloworld
这里使用的lambda表达式跟下面的效果是一样的:defadd(x,y):。。。returnxy。。。add(2,3)5
lambda表达式典型的使用场景是排序或数据reduce等:names〔DavidBeazley,BrianJones,。。。RaymondHettinger,NedBatchelder〕sorted(names,keylambdaname:name。split()〔1〕。lower())〔NedBatchelder,DavidBeazley,RaymondHettinger,BrianJones〕讨论
尽管lambda表达式允许你定义简单函数,但是它的使用是有限制的。你只能指定单个表达式,它的值就是最后的返回值。也就是说不能包含其他的语言特性了,包括多个语句、条件表达式、迭代以及异常处理等等。你可以不使用lambda表达式就能编写大部分python代码。但是,当有人编写大量计算表达式值的短小函数或者需要用户提供回调函数的程序的时候,你就会看到lambda表达式的身影了。
匿名函数捕获变量值问题
你用lambda定义了一个匿名函数,并想在定义时捕获到某些变量的值。解决方案
先看下下面代码的效果:x10alambday:xyx20blambday:xy
现在问你,a(10)和b(10)返回的结果是什么?如果你认为结果20和30,那么你就错了:a(10)30b(10)30
这其中的奥妙在于lambda表达式中的x是一个自由变量,在运行时绑定值,而不是定义时就绑定,这跟函数的默认值参数定义是不同的。因此,在调用这个lambda表达式的时候,x的值是执行时的值。例如:x15a(10)25x3a(10)13
如果你想让某个匿名函数在定义时就捕获到值,可以将那个参数值定义成默认参数即可,就像下面这样:x10alambday,xx:xyx20blambday,xx:xya(10)20b(10)30讨论
在这里列出来的问题是新手很容易犯的错误,有些新手可能会不恰当的使用lambda表达式。比如,通过在一个循环或列表推导中创建一个lambda表达式列表,并期望函数能在定义时就记住每次的迭代值。例如:funcs〔lambdax:xnforninrange(5)〕forfinfuncs:。。。print(f(0))。。。44444
但是实际效果是运行时n的值为迭代的最后一个值。现在我们用另一种方式修改一下:funcs〔lambdax,nn:xnforninrange(5)〕forfinfuncs:。。。print(f(0))。。。01234
通过使用函数默认值参数形式,lambda函数在定义时就能绑定到值。