Python lambda

引言

前段时间,没事儿时翻看了自己刚参加工作时写的一些代码,发现代码中有好几处分别都用到了lambda表达式,从代码中会发现那时候的自己对lambda理解的不算深刻,lambda的本质,为什么要用lambda而不用def定义函数等这些都没有系统的掌握。于是后面花了一些时间重新梳理了自己对lambda的认识。

lambda介绍

lambda是python中的一个关键字,实际开发中常用lambda表达式的方式创建匿名函数,比如 lambda a, b: a+b,表示定义了一个匿名函数,该函数包含a、b两个参数,并返回a与b的和。lambda表达式返回的是一个函数对象,可通过函数对象来调用定义的匿名函数,比如my_func = lambda a, b: a+b,my_func(2, 3)则表示调用lambda定义的匿名函数;(lambda a, b: a + b)(2, 3)则是另一种调用方式,具体操作如下:

>>> my_func = lambda a, b: a + b
>>> type(my_func)
<type 'function'>
>>> my_func
<function <lambda> at 0x0000000002E60438>
>>> my_func(2, 3)
5
>>> (lambda a, b: a + b)(2, 3)
5
剖析lambda创建匿名函数

lambda定义匿名函数的格式为:lambda parameters: expression,其中parameters表示定义一个或多个参数,参数类型与def一样,支持普通参数、默认参数、可变参数、关键字参数。lambda定义的匿名函数等价于如下的函数定义:

def <lambda> (parametes):
    return expression

# <lambda>指函数名称 

比如:lambda x: x + 2 等价于 def func_name(x): return x + 2;lambda a, b: a ** b 等价于 def func_name(a, b): return a ** b。其中func_name是自定义的函数名,我们也可以通过dis工具分析def与lambda定义的两类函数的字节码的关系:

>>> import dis
>>> def my_func(a, b, c):
        return (a + b) * c

>>> dis.dis(my_func)
  3           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (b)
              6 BINARY_ADD          
              7 LOAD_FAST                2 (c)
             10 BINARY_MULTIPLY     
             11 RETURN_VALUE        
>>> dis.dis(lambda a, b, c: (a + b) * c)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (b)
              6 BINARY_ADD          
              7 LOAD_FAST                2 (c)
             10 BINARY_MULTIPLY     
             11 RETURN_VALUE
             
可知,两个函数分别都是先对a、b变量做引用的push stack操作,然后执行相加,
紧接着对变量c做push stack操作,接着与a、b的和进行相乘,最后返回结果   

再次说明lambda parameters: expression 等价于 def <lambda> (parametes): return expression

lambda特点
  1. lambda是一个表达式,而不是一个语句
    lambda_expr ::= "lambda" [parameter_list]: expression

  2. lambda是只有一行的简单表达式,并不能扩展成一个多行的代码块
    Python文档说到,lambda不能包含语句,这是因为Python的语法框架无法处理嵌套在表达式中的语句。lambda可以接收多个参数,但只能有一个包含这些参数计算的表达式。这意味着lambda中不会含有if... elif... else 或者 try... except等语句,lambda的设计主要是用来计算简单的任务。

lambda使用场景

在平时的开发过程中,使用def而非lambda定义函数足够完成各种功能的开发,但适当的使用lambda能够让我们的代码更加简洁明了。那在什么样的场景下推荐使用lambda呢?

  1. 一个小的功能函数,只需要一行就能完成,且只会被调用一次
    比如要对整数列表中的所有元素添加存储单位的操作:
>>> def add_unit(num):
        return '{}mb'.format(num)

>>> map(add_unit, range(5))
['0mb', '1mb', '2mb', '3mb', '4mb']

>>> map(lambda n: '{}mb'.format(n), range(5))
['0mb', '1mb', '2mb', '3mb', '4mb']

# 可见,使用lambda的代码更加简洁
  1. 编程中与高阶函数联合使用
    实际开发中,lambda更多的是与map、filter、reduce等高阶函数搭配使用,因为这些函数中需要接收函数对象作为参数,使用lambda达到了既定义函数又传递函数的目的,比如map(lambda x: x ** 2, range(5)),这里的lambda x: x ** 2先定义函数,然后将此函数对象作为参数传递给map;如果是def则需要首先在外部定义这个函数,而不能在map函数中直接通过def来定义,map(def..., range(5)),Python不允许这样的语法。
lambda注意点

上面讲到lambda的特点是只能有一个表达式,使用lambda的目的是为了让代码更加简洁明了,所以在使用过程中需要注意以下几点:

  1. lambda专注完成简单的任务,其表达式要易读
    不推荐在编码中为了使用lambda而将表达式写的很繁琐,就像Python文档中说到的reduce(lambda a, b: (0, a[1] + b[1]), items)[1]这个表达式,你能很快看出lambda函数的意图吗?答案是不能,所以对于复杂点的逻辑,最好不要用lambda

  2. 程序中多处都会用一个小函数功能,则建议用def定义这个小函数
    对列表中的数字求平方,lambda表达式为lambda n: n ** 2,简单,易读。如果程序中不止一处需要对数字求平方,若均使用lambda,则显得代码冗余

  3. 开发中先def,后lambda
    在实际开发过程中,我倾向于把不管什么类型的函数均先通过def来定义,等程序开发接近尾声的时候,再依据简单任务、只用一次的原则看看把哪些def定义的函数可以替换成lambda匿名函数,并写上必要的注释

  4. 谨慎使用lambda
    其实从Python文档函数式编程的说明部分可以了解到,文档作者倾向于不使用lambda,原因就是lambda的单个表达式、无法扩展多行代码块等自身的功能限制。所以我们一定要秉持小函数、简单任务、只用一次的原则来决定是否要用lambda,千万别写出了大家半天都看不太明白的lambda表达式

总结

花了一些时间,重新梳理了自己对lambda的认识,Python文档常把lambda与小函数绑定在一起,因此我们对lambda的使用要依据小函数、简单任务、只用一次的原则。引入lambda是为了让代码更加简洁明了,万不可为了少写代码、为了简洁而写出了很复杂的表达式,简洁明了与易读都是需要的。以上就是我对lambda的认识,您有什么不一样的看法吗?欢迎一起交流。

引用
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280

推荐阅读更多精彩内容