読者です 読者をやめる 読者になる 読者になる

<Python> lambda って後だしの関数を呼べる?

Flask-Loginのコードを見ていて、悩んだ。

/c/Anaconda/Lib/site-packages/flask_login.pyを見ると、

46行目にlambdaがある。

44 #: A proxy for the current user. If no user is logged in, this will be an
45 #: anonymous user
46 current_user = LocalProxy(lambda: _get_user())

このlambdaのボディー部の_get_user()は、
ずっと下の792行目にある。

792 def _get_user():
793     if has_request_context() and not hasattr(_request_ctx_stack.top, 'user'):
794         current_app.login_manager._load_user()

lambdaを使うと、関数 functionを後に定義してもいいのか???

試してみた。
aaa.pyちゅう簡単なものを作る。
ABlambdaで、後に定義されたdef aaaを呼び出す。

In [95]: more aaa.py
def ccc():
    return 20


A = lambda: aaa()
B = lambda: aaa
# B = aaa
C = ccc


def aaa():
    return 5

In [96]: run aaa.py

In [97]: A
Out[97]: <function __main__.<lambda>>

In [98]: B
Out[98]: <function __main__.<lambda>>

In [99]: C
Out[99]: <function __main__.ccc>

In [100]: A()
Out[100]: 5

In [101]: B()
Out[101]: <function __main__.aaa>

In [102]: C()
Out[102]: 20

In [103]: B()()
Out[103]: 5

なんか動くね。

んじゃ、B = aaaってやって、lambdaをはずしたら、

In [104]: more aaa.py
def ccc():
    return 20


A = lambda: aaa()
B = lambda: aaa
B = aaa
C = ccc


def aaa():
    return 5

In [105]: run aaa.py
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
C:\msys64\home\numeda\python\work_lambda\aaa.py in <module>()
      5 A = lambda: aaa()
      6 B = lambda: aaa
----> 7 B = aaa
      8 C = ccc
      9 

NameError: name 'aaa' is not defined

aaaがねーよ、、って怒られた。

ふーん。

ちなみに、関数中から呼ぶ関数も後に定義してもいいっぽい。

In [108]: more aaa.py
def ccc():
    x = aaa()             # このaaa()は後半で定義してる。   
    return 20, x


A = lambda: aaa()
B = lambda: aaa
# B = aaa
C = ccc


def aaa():
    return 5

In [109]: run aaa.py

In [110]: ccc()
Out[110]: (20, 5)

ふーん。

なんでもかんでも、呼ばれるものは、先に定義しなければいかんかと思ってた。