Python:从字符串名称调用函数

İlk*_*ğlı 72 python

我有一个str对象,例如:menu = 'install'.我想从这个字符串运行install方法.例如,当我打电话时,menu(some, arguments)它会打电话install(some, arguments).有没有办法做到这一点?

Sam*_*lan 110

如果它在一个类中,你可以使用getattr:

class MyClass(object):
    def install(self):
          print "In install"

method_name = 'install' # set by the command line options
my_cls = MyClass()

method = None
try:
    method = getattr(my_cls, method_name)
except AttributeError:
    raise NotImplementedError("Class `{}` does not implement `{}`".format(my_cls.__class__.__name__, method_name))

method()
Run Code Online (Sandbox Code Playgroud)

或者如果它是一个功能:

def install():
       print "In install"

method_name = 'install' # set by the command line options
possibles = globals().copy()
possibles.update(locals())
method = possibles.get(method_name)
if not method:
     raise NotImplementedError("Method %s not implemented" % method_name)
method()
Run Code Online (Sandbox Code Playgroud)

  • 后者在变异之前不会使用.copy()全局变量,从而引发各种麻烦.并且它有一个错误,因为它在检查之前立即调用该方法,然后再次调用其结果.此外,通常的做法是使用前缀,以防止只调用命名空间中的任何元素(例如"do_install()"). (5认同)

con*_*dle 57

你也可以使用字典.

def install():
    print "In install"

methods = {'install': install}

method_name = 'install' # set by the command line options
if method_name in methods:
    methods[method_name]() # + argument list of course
else:
    raise Exception("Method %s not implemented" % method_name)
Run Code Online (Sandbox Code Playgroud)

  • 我相信使用字典更加干净,依赖于globals().copy()在接受的答案中. (8认同)

Hus*_*aty 35

为什么我们不能使用eval()?

def install():
    print "In install"
Run Code Online (Sandbox Code Playgroud)

新方法

def installWithOptions(var1, var2):
    print "In install with options " + var1 + " " + var2
Run Code Online (Sandbox Code Playgroud)

然后你调用下面的方法

method_name1 = 'install()'
method_name2 = 'installWithOptions("a","b")'
eval(method_name1)
eval(method_name2)
Run Code Online (Sandbox Code Playgroud)

这给出了输出

In install
In install with options a b
Run Code Online (Sandbox Code Playgroud)

  • 是的,它也以相同的方式使用参数. (3认同)
  • 如果您使用上述策略,则意味着您正在动态定义您的方法/功能,换句话说,它们可能是很多东西,包括恶意代码.我建议你[本文](http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html),然后再也不再使用eval了.需要时,只需使用`json`. (3认同)
  • `eval(method_name1)(a,b)` 也有效。关于安全性的公平观点——对于小型私人脚本来说是可以的,但是它们会保持这种状态吗?例如,如果字符串来自网站,请务必小心。这里唯一的问题并不是“eval”——对任意来源的字符串使用“getattr”同样危险。 (2认同)