【问题标题】:Prevent if, elif, else chain (checking input)防止 if、elif、else 链(检查输入)
【发布时间】:2020-01-17 15:48:46
【问题描述】:

如果我声明这些函数:

def f1(someval):
    print(someval)

def f2(someval, someval2):
    print(someval, someval2)

如果我有一本包含函数作为值的字典:

input_dict = {"func1": f1, "func2": f2}

我想检查用户的输入是否与字典“input_dict”中的键匹配:

shell_input = 'shell~: '
for key,val in input_dict:
    if key == shell_input:
        input_dict[val](params)

我如何检测每个被调用的函数有多少个函数参数并将值传递给它们,甚至可能(不声明全局变量)?

我试图避免在我的代码中使用链式 if、elif、else 逻辑,例如:

if shell_input == "func1":
    f1(param)
elif shell_input == "func2":
    f2(param1, param2)
#etc...

或者在检查输入时使用链式 if、elif、else 逻辑是否更有效?

【问题讨论】:

  • 我不确定你的问题,问题是参数的数量,还是它们的性质,即使用哪个?
  • 哪个使用效率更高

标签: python-3.x dictionary if-statement input


【解决方案1】:

使用这个:

input_dict = {"func1": f1, "func2": f2}

target = input_dict.get(shell_input)
if target:
    target(*params)

如果 shell_input 不匹配任何 input_dict 键,input_dict.get(shell_input) 将返回 None。

对于参数要求,我建议将您的函数重构为:

def f1(*args):
    print(args)

def f2(*args):
    print(args)

通过这样做,两个函数将具有相同的签名,并且 target(*params) 可用于传递参数(此处使用元组扩展)。

作为一个更完整的例子:

input_dict = {'func1': (f1, (param,)), 'func2': (f2, (param, param2))}

values = input_dict.get(shell_input)
if values:
    target_func, params = values  # tuples expansion again
    target_func(*params)

注意:每个 input_dict 项都包含一个包含函数和参数的元组。

【讨论】:

  • 如果函数的参数不止一个怎么办?如何将多个参数传递给函数调用?这种技术是一种更有效的检查是否 key == shell_input 的方法。
  • 使用多个参数调用 target() 是否有效?
  • 是的,这是一个非常方便的功能。它在那里是因为函数很容易变得丑陋(参数太多)。在此处查看更多信息digitalocean.com/community/tutorials/…
【解决方案2】:

我不完全确定您要完成的工作.. 如果该值不依赖于用户输入,您可以将它们用作默认参数并调用您的函数。

def f1(someval=default_value):
    print(someval)

def f2(someval=default_value_1, someval2=default_value_2):
    print(someval, someval2)

if shell_input == "func1":
    f1()

elif shell_input == "func2":
    f2()

如果问题是关于 args 的数量,您可以使用解包。 args 将是您可以迭代的可迭代对象。它也可以用作字典。

def f1(*args):
    for arg in args:
         do 


def f2(**args):
    args1 = args["my_args"]
    args2 = args["my_other_args"]
# ex:
f2(my_args="blue", my_other_args="grey")

【讨论】: