2016-05-05 2 views
9

私はCelery/Djangoで遊んでいます。その例のcelery.pyファイルで次の行ラムダユースケース混乱

lambda:settings.INSTALLED_APPSautodiscover_tasks()で仮パラメータ packagesの実際のパラメータである
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS, force=True) 

があります。そしてsettings.INSTALLED_APPSはタプルです。

autodiscover_tasks()は、だから私の質問があり、それが渡された関数を呼び出すのいずれか、または直接それがその最初の行の一つに与えられた変数を割り当て...

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

。私はなぜこれがこのように行われたのか分からない。非常に冗長なようです。タプルの神がそれを望んでいたので、ちょうどsettings.INSTALLED_APPSを渡すのはなぜですか?代わりにそれを呼び出す無名関数を渡すのはなぜですか?私はここで何が欠けていますか?

答えて

8

Celeryは非同期なので、他の計算を実行している間はsettings.Installed_Appsは変更されないので、lambdaの中にラップすると、呼び出されるまでその値がカプセル化されます。

EDIT(コメントとして例を添加):app.autodiscover_tasksが呼び出されている間、

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

は今、この考えるとinternall計算は、いくつかの他のものが計算されて作られており、今setting.INSTALLED_APPS= 8、変数を使用したので、あなたの呼び出しは '8'の代わりに10を使用していますが、lambdaapp.autodiscover_tasks(lambda: settings.INSTALLED_APPS, force=True))にカプセル化するとが必要なときに値を得て、実際の値と同期すると8

+0

完璧です。ありがとう! –

3

ダニエルの答えに加えて、ここでは、呼び出し可能関数を渡して「遅い評価」を示すための最小限の例を示します。

>>> 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_argを使用して作成されたもので、foo2は無名関数を呼び出して現在の値foo_argを取得します。