Lambda用例混淆

时间:2016-05-05 09:26:23

标签: python

我一直在玩Celery / Django。在他们的示例celery.py文件中有以下行

app.autodiscover_tasks(lambda: settings.INSTALLED_APPS, force=True)

其中lambda:settings.INSTALLED_APPSpackages中形式参数autodiscover_tasks()的实际参数。 settings.INSTALLED_APPS是一个元组。

autodiscover_tasks()然后调用它传递的函数或者直接分配它在第一行中给出的变量......

packages = packages() if callable(packages) else packages

所以我的问题是。我只是不明白为什么这样做。这似乎非常多余。为什么不通过settings.INSTALLED_APPS作为元组神想要它。为什么传递一个调用它的匿名函数呢?我在这里缺少什么?

2 个答案:

答案 0 :(得分:8)

由于Celery是异步的,因此settings.Installed_Apps在执行其他计算时不会更改是不固定的,因此将其包装在lambda内会将其封装为引用,直到它被调用为止。

编辑(添加示例评论):

setting.INSTALLED_APPS = 10
app.autodiscover_tasks(settings.INSTALLED_APPS, force=True) #is called with installed_apps = 10, so it give you an output.

现在想到这一点,在调用app.autodiscover_tasks并且正在计算其内部计算时,正在计算其他内容,而setting.INSTALLED_APPS现在= 8,因为您确实使用了变量,您的来电正在使用10代替' 8',但是将其封装到lambdaapp.autodiscover_tasks(lambda: settings.INSTALLED_APPS, force=True))中,它将获得时的值 他需要它,与它的实际值同步,应该是8

答案 1 :(得分:3)

再加上Daniel的答案,这是一个通过传递可调用来展示“迟到评估”的一个相当小的例子。

>>> def foo(arg):
...     return lambda: arg() if callable(arg) else arg

这是一个函数,它返回另一个函数以伪造异步执行。

构建两个函数:

>>> foo_arg = 3
>>> foo1 = foo(foo_arg)
>>> foo2 = foo(lambda: foo_arg)

在创建foo_argfoo1之后更改foo2

>>> foo_arg = 4

调用函数:

>>> foo1()
3
>>> foo2()
4

foo1使用构建它的旧foo_argfoo2调用匿名函数来获取当前值foo_arg