【问题标题】:Use a string to call function in Python [duplicate]在Python中使用字符串调用函数[重复]
【发布时间】:2011-05-07 02:55:14
【问题描述】:

前几天我在网上搜索,发现一篇关于python字典的有趣文章。这是关于使用字典中的键来调用函数。在那篇文章中,作者定义了一些函数,然后是一个与函数名称完全相同的字典。然后他可以从用户那里获取一个输入参数并调用相同的方法(比如实现 case break) 在那之后,我意识到同样的事情,但不知何故不同。我想知道如何实现这一点。 如果我有一个功能:

def fullName( name = "noName", family = "noFamily" ):
    return name += family

如果我有这样的字符串:

myString = "fullName( name = 'Joe', family = 'Brand' )"

有没有办法执行这个查询并得到结果:JoeBrand
例如,我记得我们可能会给 exec() 语句一个字符串,它会为我们做这件事。但我不确定这种特殊情况,也不知道 Python 中的有效方法。我也将非常感谢帮助我如何处理该函数的返回值,例如在我的情况下如何打印该函数返回的全名?

【问题讨论】:

  • 你的函数将返回 None...使用 + 而不是 +=
  • 要完成此操作,请使用:getattr(myString, 'fullName')(name='Joe', family='Brand') [查看页面顶部链接的重复问题]
  • [注意:getattr() 用于此帖子重复的问题的最佳答案,但未在下文提及。我认为出现在此页面本身会有所帮助,因此我违反了在 cmets 中回答问题的惯例。]

标签: python string function


【解决方案1】:

这并不能完全回答你的问题,但也许它仍然有帮助:

如前所述,应尽可能避免使用eval。 imo 更好的方法是使用字典解包。这也非常动态且不易出错。

例子:

def fullName(name = "noName", family = "noFamily"):
    return name + family

functionList = {'fullName': fullName}

function = 'fullName'
parameters = {'name': 'Foo', 'family': 'Bar'}

print functionList[function](**parameters)
# prints FooBar

parameters = {'name': 'Foo'}
print functionList[function](**parameters)
# prints FoonoFamily

【讨论】:

    【解决方案2】:

    你可以使用eval():

    myString = "fullName( name = 'Joe', family = 'Brand' )"
    result = eval(myString)
    

    但请注意,eval() 被许多人视为邪恶

    【讨论】:

    • 提前谢谢,但如果我将它存储在变量中,它会从函数返回任何值吗?
    • 是的,确实如此。请参阅我的更新答案。
    • @Framester 不,这不是更好的答案,而是针对不同情况的答案。这是在询问如何调用一个函数,没有任何对象。您要推广的答案是关于调用对象的方法。
    • 我认为这是一个更好的答案,因为它避免了eval():stackoverflow.com/a/22021058/9024698。如果我没记错的话,也是下面@kirbyfan 的回答(stackoverflow.com/a/16683842/9024698)。
    【解决方案3】:

    我知道这个问题已经很老了,但你可以这样做:

    argsdict = {'name': 'Joe', 'family': 'Brand'}
    globals()['fullName'](**argsdict)
    

    argsdict 是参数字典,globals 使用字符串调用函数,** 将字典扩展为参数列表。比eval 干净得多。唯一的麻烦在于拆分字符串。一个(非常混乱的)解决方案:

    example = 'fullName(name=\'Joe\',family=\'Brand\')'
    # Split at left parenthesis
    funcname, argsstr = example.split('(')
    # Split the parameters
    argsindex = argsstr.split(',')
    # Create an empty dictionary
    argsdict = dict()
    # Remove the closing parenthesis
    # Could probably be done better with re...
    argsindex[-1] = argsindex[-1].replace(')', '')
    for item in argsindex:
        # Separate the parameter name and value
        argname, argvalue = item.split('=')
        # Add it to the dictionary
        argsdict.update({argname: argvalue})
    # Call our function
    globals()[funcname](**argsdict)
    

    【讨论】:

    • 唯一的解决方案。如果此代码驻留在一个模块中,并且该模块将在 fullName 的代码更改后重新加载,那么这些更改将在下一次调用 fullName 时生效。 Felix Kling 的答案没有这个属性,因为该函数缓存在 functionList 中,我们甚至不会谈论 eval 的想法有多糟糕。
    猜你喜欢
    • 1970-01-01
    • 2018-06-21
    • 2011-12-17
    • 2015-04-06
    • 2017-07-02
    • 2019-07-28
    • 2018-12-23
    • 2021-11-17
    • 1970-01-01
    相关资源
    最近更新 更多