2014-01-15 23 views
2

我看到這個在招聘廣告(上SO):解碼隱祕的Python聲明

lambda f: (lambda a: a(a))(lambda b: f(lambda *args: b(b)(*args))) 

所以我的理解是它是一個匿名(未命名)功能,它是由另外兩個嵌套的匿名函數。最內層的函數需要一個變量列表(* args)。

我不知道該怎麼辦。如果沒有看到實際的參數列表,這是否會實際工作或不可能分辨?

+2

你確定它是*應該*做任何事嗎? –

+0

我會第二@ mhlester的建議,這是一個生病的笑話。有可能導致無盡的遞歸?! – volcano

+2

代碼的作用可能並不清楚,但很明顯,管理員必須做的事情是:啓動程序員並獲得編寫可讀代碼的人。 – Matthias

回答

7

我已經取消了lambda,只是爲了讓它更容易閱讀。下面是一個使用嵌套函數的代碼:

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,並提供一些論據。那麼下面的事情發生:

  1. F2獲取與F3
  2. F2 F3返回調用本身作爲參數調用
  3. 現在,我們內部F3同時B是F3
  4. F3返回˚F (你用f1調用的參數)用f4作爲參數
  5. f是一個回調函數,它被函數作爲唯一參數調用
  6. 如果f調用這個函數,那麼它的調用將被應用到調用b的結果與b。b爲F3,因此f將基本上調用F3(F3)的結果,這就是f爲要回

因此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,)" 

正如你所看到的,它採用的是全球停止遞歸。

這裏有一個運行泊松分佈的試驗用的λ(拉姆達是泊松分佈,而不是拉姆達操作參數)的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

'function'應該用'def'替換。 – falsetru

+0

哇,是的,我在這裏很蠢 – CrazyCasta

+1

你應該在'f2'之外但在'f1'之內定義'f3'。 – justhalf

3

不只是*指定參數時,這是很難說什麼是不知道什麼abf*args是。

當b作爲參數傳遞給函數b時,兔子的洞變得特別深,並且這個結果是一個傳遞給args的函數。

6

該代碼正在創建Y-combinator in Python。這只是一個練習,而不是真實世界的代碼;不要試圖解密它。

要了解Y-combinator本身的功能,可以參考此SO問題:What is a y-combinator?及其wikipedia頁面:Fixed-point combinator

也許這個廣告正在尋找知道函數式編程和/或高級計算機科學主題的人,如Lambda calculusCombinatory logic,它們是函數式編程背後的主要理論基礎。

或者他們的公司是Y Combinator winner startup,他們只是在尋找具有CS背景的Python程序員。

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總是與自身調用,所以我們用f3替換b

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,))
    • 如果我們使用該元組的第0個元素:f1(f)(4)[0](1),我們得到(f4, (1,))