2012-04-19 62 views
1

我想寫一種CPS代碼更高的功能。他們應該獲取一個函數代碼,將其封裝在對象中並添加用於組合這些對象的方法。更多功能python

事情是這樣的:

myFunction=MyFunction(
    a = b+c 
    print(c) 
    return a) 

但只有一個匿名函數Python的表達 - 拉姆達聲明。它適合不太好。

Python是一種功能強大的語言,它有不同的表達式:裝飾器,eval等...有沒有一種好的方法來編寫像上面例子中的匿名函數?

其他方法是擴展lambda表達式,其中包含一次性綁定和返回等特殊函數,以及用於編寫複雜表達式單行的其他高階函數。

主要目的是創建自定義控件表達式。

class TimeoutExpression: 
    def __init__(self,name,function,timeout): 
    ... 
    def eval(self): 
    """ eval functions, print result and error message 
     if functions failed to calculate in time """ 
    ... 
    def andThen(self,otherExpression): 
    """ create complex sequential expression" 
    ... 
    def __call__(self): 
    ... 

,它是在後續的使用方式:

TimeoutExpression(time consuming calculation).andThen(
    file object access).andThen(
    other timer consuming calcualtion) 

什麼是用於創建自定義的控制流結構的最好的Python慣用方式是什麼?

我讀過討論:How to make an anonymous function in Python without Christening it? 有人提到了幾種使用相同方法的決定:從三重引用字符串生成函數。 看起來相當麻煩,而絕對正確的行爲。這是現在設計的最好方法嗎?

更新

有人告訴我,是沒有問題的,Python允許你在任何環境中使用高清。我認爲我的蟒蛇經驗欺騙了我,並試圖在建議的任何範圍中使用def。我有一個錯誤。我應該如何在任何情況下放置def

def compose(f): 
    return lambda k: lambda x: f(k(x)) 

test = compose(def sqr(x) : 
       print ("sqr "+str(x)) 
       return x*x 
       return sqr) (def x2(x): 
           print("x2 "+str(x)) 
           return x*2 
           return x2) 

錯誤:

Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
    File "anonFunction.py", line 4 
    test = compose(def sqr(x) : 
       ^
SyntaxError: invalid syntax 
+4

爲什麼它必須是匿名的? – KillianDS 2012-04-19 19:10:19

+0

複雜和單行不適合python zen – KurzedMetal 2012-04-19 19:11:04

+6

每種語言都不一樣。不要試圖用Python來編寫功能代碼,就像用另一種語言完全一樣。 – agf 2012-04-19 19:11:07

回答

3

有使用拉姆達的w.r.t Python中沒有優勢。 Lambda和Anonymous函數通常用於簡單函數,並且如果您需要更復雜的多行函數,則它更具可讀性來編寫命名函數。

由於函數是第一類對象,您可以簡單地定義它,將其分配給一個變量並使用它並傳遞它。 除非另有說明,否則您需要一個一次性的簡單函數,您可以選擇lambda的函數,命名的函數是有利的。不過也使用lambda在從未完全Pythonic。

回來到您的例子,

myFunction=MyFunction(
    a = b+c 
    print(c) 
    return a) 

在Python,寫它類似於

def MyFunction: 
    a =b + c 
    print c 
    return a 

,然後通過它在你的代碼爲MyFunction很Python的。我在Javascript中看到了回調書寫爲匿名的代碼。但是每種語言都有自己的哲學,Python的哲學是可讀性。

---可讀性計數。

+0

如果多於一次使用名稱,則命名函數很有用。我想寫這樣的:Fun(某些expr).bind(某些expr).bind(其他expr)用於創建非標準控制流,例如並行執行或超時計算等。 – ayvango 2012-04-19 19:16:21

+0

@ayvango:即使使用命名函數進行單次使用也不是一個壞的選擇。 – Abhijit 2012-04-19 19:21:18

+1

@ayvango還要注意,你可以在你想要的任何範圍內使用'def',而不僅僅是在頂層;他們也有完全關閉等等。「多線lambda」沒有多大優勢;唯一的區別是你不能直接把它作爲另一個函數的參數來寫,它通常在語法上相當混亂。 – Dougal 2012-04-19 19:26:45

1

在Python中,使用lambda關鍵字,您只能創建一個函數對象來評估單個表達式並返回結果。要使用語句或多行生成函數,您必須使用def關鍵字,它需要一個名稱。

lambda限制的原因大多是基於這樣的事實,Python的治療結束線作爲顯著的事情:

No Multiline Lambda in Python: Why not?

然而,名字並不重要。你可以制定一個約定,你的每一個「匿名」功能都將被定義爲名稱anon或其他東西。如果你真的關心,你可以刪除這個名字的痕跡:

y = 5 
def anon(x): 
    return x + y # note "closure" over the current value of y 

myFunction = anon 

# if you really care, you can erase all evidence of name "anon" 
anon.__name__ = '' # wipe the record of original name "anon" 
del(anon) # unbind the name "anon" 

所以,函數式編程,Python可以創造一流的函數對象,通過他們周圍,等的一件事Python不能做的就是創建一個複雜的函數對象,從來沒有一個名字,但真的沒有理由爲什麼這很重要。

+0

Python可以使用lambda編程技術創建具有lambda結構的任意複雜函數對象,但這很麻煩,應該只有在沒有其他選擇的情況下才能使用(例如,lisp) – ayvango 2012-04-19 19:50:05

1

我有一個破解 - 這是真正的唯一正確的術語 - 使用嵌套函數,提供多線lambda可能會給的功能。你可以看看我的GitHub倉庫here

基本上,它可以讓你做這樣的事情:

fibonacci = f('result = t(a-1)+t(a-2) if a>2 else 1; return result') 
fibonacci(6) #Output: 8 

以上的匿名功能點:

cube = f('result = a**3; return result')(4) 
print(cube) #Output: 64 

明明有這個黑客限制;例如,我仍然沒有想出一種方法來實現更復雜的縮進結構,如ifwhile,但再次,這是一個非常便宜的黑客。