2012-08-09 58 views
5
def f1(n): #accepts one argument 
    pass 

def f2(): #accepts no arguments 
    pass 

FUNCTION_LIST = [(f1,(2)), #each list entry is a tuple containing a function object and a tuple of arguments 
       (f1,(6)), 
       (f2,())] 

for f, arg in FUNCTION_LIST: 
    f(arg) 

循環中的第三次循環嘗試將參數的空元組傳遞給不接受參數的函數。它給出了錯誤TypeError: f2() takes no arguments (1 given)。前兩個函數調用正常工作 - 元組的內容獲得傳遞,而不是元組本身。Python - 函數/參數元組列表

擺脫的論據有問題的列表條目空的元組不能解決問題:

FUNCTION_LIST[2] = (f2,) 
for f,arg in FUNCTION_LIST: 
    f(arg) 

結果ValueError: need more than 1 value to unpack

我也嘗試迭代索引而不是列表元素。

for n in range(len(FUNCTION_LIST)): 
    FUNCTION_LIST[n][0](FUNCTION_LIST[n][1]) 

這給在第一種情況相同TypeError,並IndexError: tuple index out of range當列表的第三項是(f2,)

最後,星號符號也不起作用。在電話會議上這一次錯誤f1

for f,args in FUNCTION_LIST: 
    f(*args) 

TypeError: f1() argument after * must be a sequence, not int

我已經耗盡了東西試試。我仍然認爲第一個應該工作。任何人都可以將我指向正確的方向嗎?

回答

8

你在這個代碼片段註釋顯示與此相關一個誤解:

FUNCTION_LIST = [(f1,(2)), #each list entry is a tuple containing a function object and a tuple of arguments 
       (f1,(6)), 
       (f2,())] 

表達(2)(6)並不元組 - 它們都是整數。您應該使用(2,)(6,)來表示您想要的單元素元組。固定在此之後,你的循環代碼應該這樣看:

for f, args in FUNCTION_LIST: 
    f(*args) 

Unpacking Argument Lists在Python教程爲*args語法的解釋。

+0

感謝您的好評。推論問題:是否可以對函數的返回值執行操作?假設我想將第一個條目加倍:'FUNCTION_LIST = [(f1 * 2,(2,)),(f1,(6,)),(f2,())]'不起作用,您會嘗試將乘法運算符應用於函數_object_,而不是該函數返回的值。 – 2012-08-09 13:05:04

+0

相關:是否有可能在參數元組中調用其他函數,這將在函數調用時進行評估? 'FUNCTION_LIST = [(f1,(time.time(),)),(f1,(6,)),(f2,())]'不會給我一些時間依賴的,因爲時間的調用。 time()將在列表填充時進行評估。 – 2012-08-09 13:07:32

+1

@poorsod:對於延遲執行,你應該定義你想要的功能。例如'def double_f1(x):return 2 * f1(x)'或'def f1_time():return f1(time.time)'。在某些情況下,你可以用'lambda'函數逃脫,但是我建議少用一些。 – 2012-08-09 13:13:16

0

嘗試通過*()而不是()*符號告訴python解壓後面的iterable,所以它解開空的元組並且不傳遞任何東西給函數,因爲元組是空的。

2

的問題是,這樣的符號:

(6) 

計算爲整數值,你需要的元組,這麼寫是這樣的:

(6,) 

和您的星號標記法會成功。

0

爲了記錄,我發現的一個很好的選擇是使用functools.partial。下面的代碼做我想要做的:

from functools import partial 

def f1(n): #accepts one argument 
    pass 

def f2(): #accepts no arguments 
    pass 

FUNCTION_LIST = [partial(f1,2), #each list entry is a callable with the argument pre-ordained 
       partial(f1,6), 
       partial(f2)] #the call to partial is not really necessary for the entry with no arguments. 

for f in FUNCTION_LIST: f()