2012-08-09 96 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()