对python中的lambda表达式感到困惑

时间:2017-09-23 04:13:30

标签: python lambda

我理解正常的lambda表达式,例如

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 个答案:

答案 0 :(得分:2)

sets被分配了一个实际上不应该接受输入的lambda,你可以从调用它的方式看到它。 Lambda通常表现得像普通函数,因此可以分配给gsets等变量。 sets的定义被一组额外的括号包围,没有明显的理由。你可以忽略那些外在的。

Lambdas可以拥有普通函数可以使用的所有相同类型的位置,关键字和默认参数。 lambda 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])

为了说明的目的,我已经截断了lambdas以返回它们的输入参数。此示例将按预期打印['train', 'test']

如果你在没有默认参数的情况下做同样的事情,输出将是['test', 'test']而不是:

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

这是因为'test'是评估所有lambda时split的值。

答案 1 :(得分: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的地方调用它。

答案 2 :(得分:0)

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

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

sets是一个赋予匿名函数(或lambda函数)的变量。这允许通过变量sets引用和使用lambda函数。

关于你的第二个问题(为什么sets()可以被退回?),我回答:

由于sets是一个充当函数的变量,因此在调用lambda函数后添加括号。由于未给出参数,因此参数split采用值'test',这是for循环变量split所采用的最后一个值。值得注意的是,由于sets未在函数get_imdb内定义,因此解释器在sets范围之外查找get_imdb的定义(并找到一个引用lambda函数的人。)