调用未知的Python函数

调用未知的Python函数,python,Python,这是我能想到的关于这个主题的最好的名字,我的搜索结果中没有一个与这个问题相关的信息 如何从字符串调用函数,即 functions_to_call = ["func_1", "func_2", "func_3"] for f in functions_to_call: call f 编辑以添加: 是的,eval()通常是一个坏主意,但这正是OP所要寻找的。您怎么不知道要调用的函数的名称?存储函数而不是名称: functions_to_call = [int, str, float]

这是我能想到的关于这个主题的最好的名字,我的搜索结果中没有一个与这个问题相关的信息

如何从字符串调用函数,即

functions_to_call = ["func_1", "func_2", "func_3"]

for f in functions_to_call:
    call f
编辑以添加:


是的,eval()通常是一个坏主意,但这正是OP所要寻找的。

您怎么不知道要调用的函数的名称?存储函数而不是名称:

functions_to_call = [int, str, float]

value = 33.5

for function in functions_to_call:
    print "calling", function
    print "result:", function(value)
请参阅函数

此函数还可用于执行任意代码对象(例如由compile()创建的对象)。在本例中,传递代码对象而不是字符串。如果已使用'exec'作为种类参数编译代码对象,eval()的返回值将为None


类似的东西…当我在python中查看函数指针时

def myfunc(x):
    print x

dict = {
    "myfunc": myfunc
}

dict["myfunc"]("hello")

func = dict.get("myfunc")
if callable(func):
    func(10)

您可以使用python内置的locals()来获取本地声明,例如:

def f():
    print "Hello, world"

def g():
    print "Goodbye, world"

for fname in ["f", "g"]:
    fn = locals()[fname]
    print "Calling %s" % (fname)
    fn()
您可以使用“imp”模块从用户指定的python文件加载函数,这给了您更多的灵活性

使用locals()可以确保您不能调用泛型python,而使用eval,最终用户可能会将字符串设置为不正确的值,如:

f = 'open("/etc/passwd").readlines'
print eval(f+"()")

或者类似的,最终你的编程做了一些你不期望的事情。通常对locals()和dict使用类似的技巧只会给攻击者带来keyrerrors。

看看getattr函数:


不要使用eval!python中的函数几乎从来都不是必需的,它们与其他所有函数一样都是属性,可以使用类上的
getattr
或通过
locals()
进行访问:

因此,无需求助于评估的解决方案:

>>> def func_1():
...     print "one"
... 
>>> def func_2():
...     print "two"
... 
>>> def func_3():
...     print "three"
... 
>>> functions_to_call = ["func_1", "func_2", "func_3"]
>>> for fname in functions_to_call:
...     cur_func = locals()[fname]
...     cur_func()
... 
one
two
three


我可以解释所有关于确切程序的内容,但我觉得这会浪费空间,会分散对手头具体问题的注意力。函数在问题中存储为字符串,而在你的答案中不是这样,因此答案不完全正确…@sykora。。。但是如果你能稍微改变一下你的问题的要求,它确实展示了一个更好的方法;存储函数本身。@nosklo,你介意更详细地解释一下为什么eval不好吗?或者链接到解释它的资源…+1 dispatch dict是一种很好的方法,如果你真的需要一个字符串+1来表示想法(这也允许你将可调用的内容限制到一个特定的集合),但是虚拟-1用于调用字典“dict”,这将在本地范围中隐藏类型名称…每个字典都是类型“dict”的实例。它可以通过两种方式构建:要么使用语法{},要么调用构造函数“dict()”。调用变量(或任何东西)“dict”会阻止您通过调用“dict()”来构建字典,以及测试类型。当然,这也适用于任何其他内置类型,而“dict”本身并不重要。但是,这仍然非常有效,我不知道为什么它的投票数如此之少。-1感谢没有提到使用eval总体上是个坏主意。的确。这里没有理由使用eval()
locals()[f]()
就可以了。这仍然是一种非常值得怀疑的方法,但比eval()更好。getattr使用字符串工作得更好,这也是OP所寻找的。我们不应该传播eval(),因为getattr()也可以做得很好。@nosklo,每个答案真的需要提到eval不好吗?如果您在自己的答案中只将eval函数的残暴性区分开来,这可能就足够了。-1感谢您没有提到使用exec/eval总体上是个坏主意。当您似乎知道您只想从列表中调用的函数时,函数名可能来自外部源,就像一个文本文件。它是一个运行游戏的半抽象系统(所以我可以重用它),因此它们可以从一个文本文件中接近。
import sys

functions_to_call = ["func_1", "func_2", "func_3"]

for f in functions_to_call:
  getattr(sys.modules[__name__], f)()
>>> print locals()
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__name__': '__main__',
 'func_1': <function func_1 at 0x74bf0>,
 'func_2': <function func_2 at 0x74c30>,
 'func_3': <function func_3 at 0x74b70>,
}
>>> f1 = locals()['func_1']
>>> f1
<function func_1 at 0x74bf0>
>>> f1()
one
>>> def func_1():
...     print "one"
... 
>>> def func_2():
...     print "two"
... 
>>> def func_3():
...     print "three"
... 
>>> functions_to_call = ["func_1", "func_2", "func_3"]
>>> for fname in functions_to_call:
...     cur_func = locals()[fname]
...     cur_func()
... 
one
two
three