2013-08-04 48 views
4
>>> list=[None] 
>>> def list[0](x,y): 
    File "<stdin>", line 1 
    def list[0](x,y): 
      ^
SyntaxError: invalid syntax 

如何將函數定義爲列表元素?將函數定義爲列表元素

+1

你到底想幹什麼?我認爲你想要的是你不應該做的事情,但即使如此,我不知道你在問什麼 – TerryA

+4

爲什麼這麼多用戶低估了這個合法的問題讓我印象深刻。 – Hyperboreus

+1

這是一個完全合法的問題。其他一些語言確實允許通用的左值(不僅僅是標識符)作爲函數定義的目標。 OP合理地認爲Python可能支持功能定義目標中的類似靈活性。 –

回答

11

Python的def不夠靈活,無法處理通用lvalues,如list[0]。該語言只允許您使用標識符作爲函數名稱。下面是grammar rule for the def-statement的相關部分:

funcdef  ::= "def" funcname "(" [parameter_list] ")" ":" suite 
funcname  ::= identifier 

相反,你可以使用一系列的分配和定義語句:

s = [None] 

def f(x, y): 
    return x + y 

s[0] = f 

作爲替代方案,你也可以直接存儲lambda expression在列表:

​​
9
def f(whatever): 
    do_stuff() 

l[0] = f 

函數定義語法不允許您直接定義一個函數到數據結構,但你可以創建功能,那麼無論它需要去指定。

+0

或'l = []; l.append(f)' – SethMMorton

+2

@SethMMorton:或者只是'l = [f]'如果你正在控制'l'的創建,而不是試圖將函數分配到現有的位置,但我認爲這會更清晰。 – user2357112

4
def someFunctionA(x, y): 
    return x+y 

def someFunctionB(x, y): 
    return x*y 

someList = [someFunctionA, someFunctionB] 

print someList[0](2, 3) 
print someList[1](5, 5) 
+2

爲什麼不'l = [someFunctionA,someFunctionB]'? (此外,最好不要使用'list'作爲標識符。) – glglgl

+0

我這樣做了,但有一個錯誤,並認爲lambda是必要的。現在它可以工作,但顯然lambda是多餘的。 +1! – Akinakes

+3

我認爲關於使用'list'作爲標識符的投訴是站得住腳的。陰影列表不好。 – tacaswell

2

允許這樣的自由將使解析較硬的......例如括號表達式

...(x, y, z=3) 

可以是參數聲明(其中3爲關鍵字參數z缺省值)或呼叫(即傳遞z關鍵字參數值作爲3)。

如果你想允許def通用分配表示你還需要允許

def foo(x, y, z=3)[3](x, y, z=3): 
    ... 

,其中第一個括號部分具有從第二部分不同的語義和語法規則。

爲此編寫一個解析器很煩人(基本上是因爲你需要處理一個任意的無限量的源代碼而不理解它),這就是例如導致我知道的整個宇宙中最差的解析規則(這是可怕的C++的most vexing parse),基本上放棄了試圖通過辭退歧義來獲得體面的語言。

請注意,在很多情況下,當程序難以進行解析時,這是因爲含糊不清,會讓人難以理解它。

Python正確地將可讀性看作非常重要。在Python

函數是但第一類對象,所以你可以解決你的問題很容易就夠了:

def foo(...): 
    ... 

mylist[index] = foo 

或者,只有當函數是一個單一的表達,與

mylist[index] = lambda ... : ... 

(但lambda是非常有限的,這既是因爲它在Python社區中有點「討厭」,也因爲它會在語法級別造成一些煩惱,因爲需要處理括號內的縮進)。

還要注意,一些Python新手不知道的是,即使在函數內部也可以使用def;例如:

def register_http(): 
    def handle_http(connection): 
     ... 
    global_register['http'] = handle_http 

將分配一個功能作爲全局地圖的元件,而不與它的名稱污染全局(模塊)的命名空間。本地def也可以通過捕獲本地狀態變量(在2.x中爲只讀,甚至在3.x中讀/寫)來創建閉包。

還要注意,如果你需要一些功能的處理可能是decorators可能是有用的。例如通過定義

def register(name): 
    def do_registering(f): 
     global_register[name] = f 
     return f 
    return do_registering 

你可以使用

@register('http') 
def handle_http(connection): 
    ... 
+0

你是完全正確的,但是,我必須對這樣一個複雜的事情是必要的事實咆哮。有一個非常好的語法元素:裝飾器。他們可以很容易地用於此。我有時做的是返回或產生一個函數,但裝飾器不適用於語句。然而,'@ return'或'@ yield'應該是相當不錯的。在這種情況下,我們可以在這之前有一個'@ = target'(因爲分配目標位於右邊而會變得醜陋),或者'@@ target',比如'@@ global_register ['http']'函數,在函數之後不需要醜陋的賦值/產量/返回行。 – glglgl

+0

@glglgl:你可以做比使用'@register('http')''等參數化裝飾器更簡單的事情。他們有點奇怪的實現(參數化裝飾器必須返回一個非參數化的裝飾器函數),但他們很好用。請參閱編輯。 – 6502

+0

對,在這種情況下,這是一個不錯的選擇;我忘了那個。但是,唉,不能用於簡化「yield」或「return」之類的東西。 – glglgl

相關問題