在Python中使用字符串调用函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Python中使用字符串调用函数相关的知识,希望对你有一定的参考价值。
参考技术A 已有字符串形式的函数名称,那么如何调用这个函数呢?通过调用内置函数locals()和globals()返回的字典对象,就可以可以获得名称与对象的映射关系。其中,locals()仅在全局范围内调用时可以获得函数对象。 我们来看以下的例子。
需要注意的是,使用上述方法通过字符串调用函数时,为了系统的安全,防止执行任意函数,需要对函数名做一些处理,也就是使用统一的前缀为这些函数命名。例如在上述例子中,使用前缀cmd_+函数名的形式定义函数(cmd_help,cmd_sum)。
在传入函数名字符串时,只传入函数名的后半部分(如"help","sum"),由程序添加前缀后组成完整的函数名,再调用该函数。
对于类的成员函数,则可以使用getattr()获得类成员函数。
上述代码通过字符串调用了类成员函数,与前一段代码执行的结果相同。
此外,还可以使用字典将字符串与函数对应起来调用,缺点就是每增加一个函数需要相应在字典对象中添加相应的键值,增加代码维护工作量。
以上代码在Python 3.6以上运行通过。
在Python中使用字符串调用函数[重复]
【中文标题】在Python中使用字符串调用函数[重复]【英文标题】:Use a string to call function in Python [duplicate] 【发布时间】: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 中回答问题的惯例。] 【参考方案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()
被许多人视为邪恶。
【讨论】:
提前谢谢,但如果我将它存储在变量中,它会从函数返回任何值吗? 是的,确实如此。请参阅我的更新答案。 更好的答案:***.com/questions/3061/… @Framester 不,这不是更好的答案,而是针对不同情况的答案。这是在询问如何调用一个函数,没有任何对象。您要推广的答案是关于调用对象的方法。 我认为这是一个更好的答案,因为它避免了eval()
:***.com/a/22021058/9024698。如果我没记错的话,也是下面@kirbyfan 的回答(***.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
的想法有多糟糕。以上是关于在Python中使用字符串调用函数的主要内容,如果未能解决你的问题,请参考以下文章