关于lambda s:s

在某前辈的代码中发现这么一句:

_=lambda s:s

当时不太理解这么写的目的,google之后明白了(顺便吐槽百度,搜“lambda s:s”出来的结果没几个有用的),记录如下:

一般情况下出现这种写法应该是用在"and_or"技巧中,也可以叫做“逻辑短路”。相信学过C语言的一定很熟悉“and一假为假、or一真为真”这句话。

python中lambda的bool值永远为真(这里指lambda本身而不是它的返回值),《dive into python》原文翻译:

lambda函数在布尔环境中总是为真。(这并不意味这lambda函数不能返回假值。这个函数对象的布尔值为真;它的返回值可以是任何东西。)

python对于逻辑表达式 从左到右 进行处理,对于and,一旦出现为false(0_、‘’、[]、()、{}、None_)的值,则 **返回这个值**。如果全为true,则返回最后一个值。对于or,一旦出现为true的值,则 **返回这个值**。若全为false,则返回最后一个值。

《dive into python》中有一个实例:processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)

processFunc 现在是一个函数,但是它到底是哪一个函数还要取决于collapse变量。如果collapse为真,processFunc(_string_)将压缩空白;否则processFunc</tt>(_string_)将返回未改变的参数。

因为上面说了,lambda的bool值始终为真,若collapse为真,则第一步的返回值就是第一个lambda表达式,第二步的or直接返回了第一个lambda表达式。

若collapse为假,第一步and返回假,随后的or返回第二个lambda表达式,即返回了原字符串。

那么,为什么要把一个返回原值的lambda表达式命名为一个下划线呢?

在django中,和_最有关的可能就是I18n了,i18n = i followed by 18 letters followed by n = internationalization,可以简单理解为本地化语言,不过我在随后的代码中却没发现有相关的蛛丝马迹。

难道是本来这个程序想有这个国际化翻译功能,但不知道什么原因没实现?而且也没有类似于_(“abc”)的这种用法,连上面讲的那种短路用法都没有……

不管怎么说吧,感谢某前辈留下了这么一句“无用代码”让我学习,哈哈!

再补充一个简化例子:

def a():
    print "in a"
def b():
    print "in b"
c = True and a or b
d = False and a or b
c()
d()

结果大家可以自己试试。