使用Python中的字典调用带参数的函数

Rub*_*922 6 python parameters dictionary function

我正在制作一个程序,它有一个主菜单,要求用户输入一个选项并将其存储在整数中option1,这在字典中查找options.然后运行相应的功能.如果函数没有参数,则以下代码有效:

options = {0 : FunctionZero,    # Assign functions to the dictionary
            1 : FunctionOne,
            2 : FunctionTwo,
            3 : FunctionThree}

options[option1]()    # Call the function
Run Code Online (Sandbox Code Playgroud)

如果函数有参数,上面的代码不起作用,因为该()部分假定函数没有参数,但我尝试了以下内容,它将函数的名称和参数存储在字典中的元组中:

options = {0 : (FunctionZero,""),    # FunctionsZero, FunctionOne
            1 : (FunctionOne,""),    # and FunctionTwo have no parameters
            2 : (FunctionTwo,""),
            3 : (FunctionThree,True)}    # FunctionThree has one parameter

if options[option1][1] == "":    # Call the function
    options[option1][0]()
else:
    options[option1][0](options[option1][1])
Run Code Online (Sandbox Code Playgroud)

这段代码似乎工作正常,但我想知道是否有更好的方法来做到这一点,特别是如果函数需要几个参数?在像C#这样的其他语言中,我可能会使用switch或case语句(不在Python中)而且我避免使用if...elif语句.

jon*_*rpe 12

我这样做functools.partial是为了在创建字典时指定参数:

from functools import partial

options = {0: FunctionZero,   
           1: FunctionOne,    
           2: FunctionTwo,
           3: partial(FunctionThree, True)} 
Run Code Online (Sandbox Code Playgroud)

请注意,这也允许在调用函数时传递其他参数(只要字典中的所有函数在partial调用后都缺少相同的参数):

def test(one, two, three=None, four=None):
    ...

def test2(one, two, three=None):
    ...

options = {1: partial(test, 1, three=3, four=4),
           2: partial(test2, 1, three=3)}

...

options[choice](2) # pass the 'two' argument both functions still require
Run Code Online (Sandbox Code Playgroud)


ick*_*fay 6

当然.在Python中,函数可以采用位置或关键字参数.对于大多数函数,参数可以以任何一种方式传递,但对于所有函数都不一定如此,因此我们需要将它们分开.位置参数位于可迭代(通常是列表或元组)中,关键字参数位于从字符串到值的字典中.

然后,我们可以将每个函数表示为函数,位置参数和关键字参数的元组:

options = {
    0: (function_zero, [], {}),
    1: (function_one, [], {}),
    2: (function_two, [], {}),
    3: (function_three, [True], {}),
    4: (function_four, [], {'kwarg': True}),  # takes a keyword argument
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样打电话给他们:

func, args, kwargs = options[option1]
func(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

但是如果你总是要传递一个常量,那么有一个更好的方法:只需为调用函数的每个函数创建几个无参数包装器,如何调用:

options = {
    0: function_zero,
    1: function_one,
    2: function_two,
    3: lambda: function_three(True),
    4: lambda: function_four(kwarg=True),
}
Run Code Online (Sandbox Code Playgroud)

然后使用你的第一种方法:

options[option1]()
Run Code Online (Sandbox Code Playgroud)

正如jonrsharpe的回答中所详述,你也可以使用functools.partial而不是a lambda.正如他所指出的,这具有能够附加一些你自己的论点的优点:

options[option1]('hello')  # adds 'hello' to previously-specified arguments
Run Code Online (Sandbox Code Playgroud)

但是,如果您不需要此功能,零参数lambda将为您提供服务.