奇怪的嵌套Python lambda



这个python lambda是如何工作的?

lambda v1: (lambda v2: v1(v2(v2)))(lambda v3: v1(lambda v4: v3(v3)(v4)))

我的理解:

  1. lambda v3: v1(lambda v4: v3(v3)(v4))成为参数v1,语句变得lambda v2: v1(v2(v2))v1绑定到lambda v3: v1(lambda v4: v3(v3)(v4))
  2. 但是v1lambda v3: v1(lambda v4: v3(v3)(v4))的地位如何?对自己的引用?

你通常可以通过将其转换为标准函数并将其分解来弄清楚这样的事情(至少是这个的更简单版本):

f1 = lambda v1: (lambda v2: v1(v2(v2)))(lambda v3: v1(lambda v4: v3(v3)(v4)))

成为

def f1(v1): 
f2 = lambda v2: v1(v2(v2))
f3 = lambda v3: v1(lambda v4: v3(v3)(v4))
return f2(f3)

成为

def f1(v1): 
def f2(v2):
return v1(v2(v2)))
def f3(v3):
def f4(v4):
return v3(v3)(v4)
return v1(f4)
return f2(f3)

所以f1有两个主要部分。它定义了两个函数,我称之为f2f3。然后,它以f3作为参数调用f2并返回结果。v1f1的参数对这两个函数都是可见的。

我们也许可以抽象地讨论f2f3做什么,但由于它们只会被调用一次,因此将它们转换为直接运行的更直接的代码而不是定义为函数可能会更简单。

前一个块可以通过用等效代码替换f2(f3)变成这样:

def f1(v1):
def f3(v3):
def f4(v4):
return v3(v3)(v4)
return v1(f4)
return v1(f3(f3))

请注意,使用f3的这个定义,r = f3(f3)等效于以下内容,我们将外部调用替换为f3的内部代码:

# equivalent to r = f3(f3):
v3 = f3
def f4(v4):
return v3(v3)(v4)
r = v1(f4)

经过一些重命名,相当于

def f(v):
return f3(f3)(v)
r = v1(f)

所以每当我们看到f3(f3),我们都可以用v1(f)替换它,f定义如下所示。

如果我们在f(v)函数本身内对f3(f3)进行相同的替换,我们得到

def f(v):
return v1(f)(v)
r = v1(f)

用这个代替f1定义中的f3(f3)给出

def f1(v1):
def f(v):
return v1(f)(v)
return v1(v1(f))

因此,除非我犯了错误,否则f1是一个接受另一个函数v1作为其参数的函数。v1应该是一个接受另一个函数作为其参数并返回一个函数的函数。然后f1将定义这个奇怪的小函数f并将其传递给v1。它将获取该结果(另一个函数)并将其再次传递给v1。然后它将返回该结果(大概是另一个函数)。该函数的性质取决于调用该函数时传递给f1v1函数。

通过调查反汇编,我发现:

a = lambda v1: (lambda v2: v1(v2(v2)))(lambda v3: v1(lambda v4: v3(v3)(v4)))
a(lambda x1: x1)

以这种方式运行:

  1. 它传递lambda x1: x1作为a的参数v1,并调用a,这是lambda v1:
  2. 然后 lambda 遇到lambda v2: v1(v2(v2))
  3. 它首先加载函数lambda v2: v1(v2(v2)),并将lambda v3: v1(lambda v4: v3(v3)(v4))打包为名为v2的函数参数,并调用函数lambda v2: v1(v2(v2))
  4. lambda v2: v1(v2(v2))中,它调用v2并将自己作为参数传递,命名为v3v1(又名lambda x1: x1)也被传递。
  5. 它跳转到lambda v3: v1(lambda v4: v3(v3)(v4)),并调用lambda x1: x1,直接返回参数:lambda v4: v3(v3)(v4)
  6. 一切都返回,值lambda v4: v3(v3)(v4)从这个复杂的 lambda 返回。

最新更新