【问题标题】:How to generate dynamic function name and call it using user input in Python如何在 Python 中使用用户输入生成动态函数名并调用它
【发布时间】:2018-09-17 06:06:30
【问题描述】:

我有 10 到 20 个前缀名称相同的函数,我必须根据用户输入调用它们,但我不知道如何调用它们,我尝试使用下面的方法但它不起作用,谁能告诉我应该怎么做我使函数可调用。

def pattern_1(no):
    print('First Pattern with ' +str(no)+ ' rows')

def pattern_2(no):
    print('Second Pattern with ' +str(no)+ ' rows')


rows = eval(input('Enter number of rows: '))
pattern_no = eval(input('Enter pattern num [1-10]: '))

cust_fun_name = 'pattern_' + str(pattern_no)

print(cust_fun_name) # Here its print pattern_2 but why function is not get invoked
cust_fun_name()

当我在上面运行代码时出现以下错误

Traceback (most recent call last):                                                                                
  File "/home/main.py", line 22, in <module>                                                                      
    cust_fun_name()                                                                                               
TypeError: 'str' object is not callable

【问题讨论】:

    标签: python python-3.x function


    【解决方案1】:

    如果映射是静态的,要么将函数名映射到函数对象

    mapping = {
      "pattern_1": pattern_1,
      "pattern_2": pattern_2
    }
    
    #do not use `eval` on user input!
    pattern_no = input('Enter pattern num [1-10]: ')
    
    cust_fun_name = 'pattern_' + str(pattern_no)
    cust_func = mapping[cust_fun_name]
    # call the function
    cust_func()
    

    或者直接从本地命名空间获取函数对象

    cust_func = locals()['pattern_' + str(pattern_no)]
    cust_func()
    

    【讨论】:

    • Eval 是邪恶的。无论是 Python、PHP 还是其他任何东西。让我赞成告诉 OP
    • 所以在这种情况下,只要添加了新函数,就必须将该函数添加到映射变量中。感谢您的回答,它解决了我的问题。
    • @GajananKolpuke 是的,如果您使用第一种方法,那么您必须更新映射。如果您决定使用替代 locals()[...],那么您无需进行任何更新,它会正常工作
    • @RobinNemeth 如何在上述场景中给 cust_func 添加 mypy 注解,因为在正常情况下,注解是在 def 语句中添加的,即 def cust_func(a: str) -> int?
    • @JohnOveriron 我认为你可以做到cust_func: Callable[[str], int] = mapping[cust_func_name]
    【解决方案2】:

    如果你真的想这样做,你可以使用eval()

    def pattern_1(no):
        print('First Pattern with ' +str(no)+ ' rows')
    
    def pattern_2(no):
        print('Second Pattern with ' +str(no)+ ' rows')
    
    rows = input('Enter number of rows: ')
    pattern_no = input('Enter pattern num [1-10]: ')
    
    cust_fun_name = 'pattern_' + pattern_no
    print(cust_fun_name) 
    eval(cust_fun_name+"("+rows+")") # This is how you use eval()
    
    # Enter number of rows: >? 10
    # Enter pattern num [1-10]: >? 1
    # pattern_1
    # First Pattern with 10 rows
    

    但是,我认为您应该遵循 Robin 的回答,这是使用 Python 的合法方式。

    【讨论】:

      【解决方案3】:
      def pattern_1(no):
          print('First Pattern with ' +str(no)+ ' rows')
      
      def pattern_2(no):
          print('Second Pattern with ' +str(no)+ ' rows')
      
      
      rows = eval(input('Enter number of rows: '))
      pattern_no = eval(input('Enter pattern num [1-10]: '))
      
      pattern_2(no)
      cust_fun_name = 'pattern_' + str(pattern_no)
      
      print(cust_fun_name) # Here its print pattern_2 but why function is not get invoked
      
      eval(cust_fun_name)()
      

      【讨论】:

      • 请编辑您的答案,因为它缺乏解释,而且pattern_2(no) 这行不知从何而来。并且最后一行无法正常执行。
      猜你喜欢
      • 2016-08-02
      • 2013-05-13
      • 1970-01-01
      • 2012-07-29
      • 2011-12-22
      • 2013-09-17
      • 1970-01-01
      • 2013-05-09
      • 1970-01-01
      相关资源
      最近更新 更多