我在招聘广告上看到了这一点(在SO上):
lambda f: (lambda a: a(a))(lambda b: f(lambda *args: b(b)(*args)))
所以我理解的是它是一个匿名(未命名)函数,它由两个进一步嵌套的匿名函数组成。最里面的函数采用一个变量的争论列表(* args)。
我无法弄清楚它应该做什么。如果没有看到实际的args列表,这实际上是否有效或无法分辨?
答案 0 :(得分:7)
我已经取消了lambdas只是为了让它更容易阅读。这是使用嵌套函数的代码:
def f1(f):
def f2(a):
return a(a)
def f3(b):
def f4(*args):
return b(b)(*args)
return f(f4)
return f2(f3)
这基本上等同于:
f1 = lambda f: (lambda a: a(a))(lambda b: f(lambda *args: b(b)(*args)))
现在让我们按照函数调用。首先,你要用一些参数调用f1。然后将发生以下情况:
因此f1可以简化为:
def f1(f):
def f3():
def f4(*args):
return f3()(*args)
return f(f4)
return f3()
现在我想出了一种方法来调用不以无限递归结束的f1:
called = False
def g1(func):
def g2(*args):
print args
return None
global called
if not called:
called = True
func(5)
else:
return g2
f1(g1) # prints "(5,)"
如您所见,它使用全局来停止递归。
这是另一个运行泊松分布试验的例子,其中lambda(lambda是Poisson分布的参数,而不是lambda算子)为10:
import random
def g3(func):
def g4(a):
def g5(b):
print a
return a+b
return g5
if random.random() < 0.1:
return g4(1)
else:
return g4(func(1))
f1(g3)
最后确定性的东西,不依赖于全球,实际上有点有趣:
def g6(func):
def g7(n):
if n > 0:
return n*func(n-1)
else:
return 1
return g7
print f1(g6)(5) # 120
print f1(g6)(6) # 720
我确信每个人都可以猜出这个函数是什么,但非常有趣的是你可以让这个奇怪的lambda表达式做一些有用的事情。
答案 1 :(得分:6)
代码正在创建Y-combinator in Python。这只是一个练习,而不是现实世界的代码;不要试图解密它。
要了解Y-combinator本身的作用,您可以参考这个SO问题:What is a y-combinator?及其维基百科页面:Fixed-point combinator。
也许这个广告正在寻找那些了解函数式编程和/或高级计算机科学主题的人,例如Lambda calculus和Combinatory logic,它们是函数式编程背后的主要理论基础。
或许他们的公司是Y Combinator winner startup,他们只是在寻找具有CS背景的Python程序员。
答案 2 :(得分:3)
不仅仅是* args,如果不知道a
,b
,f
,和 *args
是什么,很难说出它是什么
当b作为参数传递给函数b时,兔子洞特别深,并且该结果是传递args的函数。
答案 3 :(得分:2)
这是完全相同的,没有太多的嵌套:
def f1(f):
def f2(a): return a(a)
def f3(b):
def f4(*args): return b(b)(*args)
return f(f4)
return f2(f3)
f2
可以替换,所以我们得到
def f1(f):
def f3(b):
def f4(*args): return b(b)(*args)
return f(f4)
return f3(f3) # was f2(f3)
始终会自行调用 f3
,因此我们将b
替换为f3
:
def f1(f):
def f3():
def f4(*args): return f3()(*args)
return f(f4)
return f3()
那它做了什么?
我们看到f3()
返回f
返回的内容,并且应该使用任意数量的参数调用它。
f
应该使用*args
获取另一个函数的函数并返回这样的函数。
调用f1(f)
会返回f(f4)
返回的内容。
让我们测试一下:
f=lambda ff: lambda *args: ff(*args)
,f1(f)()
为我们提供了无限递归。f=lambda ff: lambda *args: (ff, args)
没有调用给定的函数,所以我们可以安全地使用它:
f1(f)(4)
为我们提供了一个元组(f4, (4,))
。f1(f)(4)[0](1)
,我们会得到(f4, (1,))
。