我理解正常的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
答案 0 :(得分:2)
sets
被分配了一个实际上不应该接受输入的lambda,你可以从调用它的方式看到它。 Lambda通常表现得像普通函数,因此可以分配给g
或sets
等变量。 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函数的人。)