我一直在玩Celery / Django。在他们的示例celery.py文件中有以下行
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS, force=True)
其中lambda:settings.INSTALLED_APPS
是packages
中形式参数autodiscover_tasks()
的实际参数。 settings.INSTALLED_APPS
是一个元组。
autodiscover_tasks()
然后调用它传递的函数或者直接分配它在第一行中给出的变量......
packages = packages() if callable(packages) else packages
所以我的问题是。我只是不明白为什么这样做。这似乎非常多余。为什么不通过settings.INSTALLED_APPS
作为元组神想要它。为什么传递一个调用它的匿名函数呢?我在这里缺少什么?
答案 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',但是将其封装到lambda
(app.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_arg
和foo1
之后更改foo2
:
>>> foo_arg = 4
调用函数:
>>> foo1()
3
>>> foo2()
4
foo1
使用构建它的旧foo_arg
,foo2
调用匿名函数来获取当前值foo_arg
。