2017-09-23 154 views
5

lambda表达式我了解正常lambda表达式,如困惑在python

g = lambda x: x**2 

然而,对于一些复杂的,我有点困惑他们。例如:

for split in ['train', 'test']: 
    sets = (lambda split=split: newspaper(split, newspaper_devkit_path)) 

def get_imdb(): 
    return sets() 

其中newspaper是一个函数。我在想什么sets是什么,为什么get_imdb函数可以返回值sets()

感谢您的帮助!

补充: 的代码实际上是从这里factory.py

+3

你确定代码是正确的吗?每次迭代都要重新赋值'sets'真的很奇怪。 –

+0

我认为这只是OP创建一个最小范例的尝试。根据问题本身,这个代码不是他自己的。 –

回答

2

sets正在被分配一个lambda,它不是真的应该接受输入,您从调用的方式看到这种输入。兰姆达斯一般表现得像正常功能,因此可以分配到像gsets这样的变量。 sets的定义由一组额外的括号包围,没有明显的原因。你可以忽略那些外面的东西。

Lambdas可以具有与普通函数相同的所有类型的位置,关键字和默认参数。 λsets具有名为split的默认参数。这是一个常见的习惯用法,以确保循环的每次迭代中的sets获得与该迭代相对应的split的值,而不是所有情况下最后一次迭代中的值。

如果没有默认参数,split将根据调用时的名称空间在lambda中进行评估。循环完成后,外部函数的名称空间中的split将只是该循环的最后一个值。

创建函数对象时立即评估默认参数。这意味着缺省参数split的值将在创建它的循环迭代中的任何位置。

您的示例有点令人误解,因为它丢弃了除最后一个之外的所有sets的实际值,从而使默认参数为lambda无意义。这里是一个例子,说明如果你保留所有的lambda表达会发生什么。首先使用默认参数:

 
sets = [] 
for split in ['train', 'test']: 
    sets.append(lambda split=split: split) 
print([fn() for fn in sets]) 

我已经截断了lambda表达式只是返回它们的输入参数,用于说明目的。如预期的那样,此示例将打印['train', 'test']

如果你不这样做的默认参数同样的事情,输出将是['test', 'test']代替:

 
sets = [] 
for split in ['train', 'test']: 
    sets.append(lambda: split) 
print([fn() for fn in sets]) 

这是因为'test'split值当所有的lambda表达式得到评估。

+0

当我们调用'fn'时,会不会有参数?以'g = lambda x:x ** 2'为例,我们需要把它叫做g(2),而g()不合理。如果它有默认参数,那么它看起来没问题,因为创建它时已经生成了这些值。但对于没有缺省参数的那些,我们是否应该在最后一个例子中使用'print([fn(split)for fn in sets])'? –

+1

在最后一个例子中,lambda函数被定义为'lambda:split',i。即它是'def func():'(不带参数的函数)。如果lambda函数使用参数,则必须定义e。 G。作为'lambda x:x ** 2'(你的第一个可以理解的例子) - 在'lambda'和':'之间带有参数名称。 – MarianD

0

lambda函数:

func = lambda x: x**2 

几乎可以等同改写:

def func(x): 
    return x**2 

使用这两种方式,你可以调用功能如下:

func(4) 

在你的榜样,

sets = lambda split=split: newspaper(split, newspaper_devkit_path) 

可以写成:

def sets(split=split): 
    return newspaper(split, newspaper_devkit_path) 

等都可以称为:

sets() 

当你写下以下内容:

def get_imdb(): 
    return sets() 

你正在定义一个“闭包”。对函数sets的引用保存在get_imdb内,以便在调用get_imdb的任何地方都可以调用该函数。

+0

您没有解决默认参数的用途,也没有说明'sets'的最后一个值被丢弃的事实。 'def get_imb():...''不*创建闭包。它只是一个正常的函数调用。 –

0

也许你对split=split部分感到困惑。这与它在常规函数中具有的含义相同:左边的分割是lambda函数的参数,右边的分割是默认值,左边的分割在没有提供值时会执行。在这种情况下,默认值将是for循环中定义的变量split

所以,回答你的第一个问题(什么是sets):

sets是其中一个匿名函数(或lambda函数)分配一个变量。这允许通过变量sets来引用和使用lambda函数。

第二个问题(为什么sets()可以退回?),我回应:

由于sets是一个变量,充当函数,在调用lambda函数后添加圆括号。因为没有给出参数,所以参数split取值'test',这是for循环变量split所采用的最后一个值。这里值得注意的是,由于sets未在函数get_imdb内部定义,因此解释程序在get_imdb范围外寻找sets的定义(并找到引用lambda函数的那个​​定义)。