在Python中动态调用函数的方法是什么?

时间:2010-10-25 21:19:03

标签: python

我想做点什么:

dct = ['do_this', 'do_that']
dct[0]() // call do_this

但是你不能将字符串作为函数调用(会出错)。

如何在不切换和不使用lambdas或函数列表的情况下实现此目的?

显然我想按名称引用该函数。

9 个答案:

答案 0 :(得分:11)

Python中的函数是first-class objects

def do_this():
    pass

def do_that():
    pass

dct = [do_this, do_that]
dct[0]()  # calls do_this()

如果dct绝对必须是字符串列表,我会选择eval()

eval(dct[0] + "()")

它并不漂亮,但在适当的模块上切换globals()getattr()可能会很痛苦。

答案 1 :(得分:9)

函数是第一类对象。像这样:

def do_this():
    print "In do_this"

def do_that():
    print "In do_that"

dct = [do_this, do_that]
dct[0]()

如果你真的想从字符串列表中调用它们,你可以使用globals():

dct = ['do_this', 'do_that']
globals()[dct[0]]()

但我建议使用globals()(或locals())可能不是解决问题的正确方法。以python方式实现:>>> import this

答案 2 :(得分:3)

如果它们在模块中,则可以使用getattr;如果它们位于全局命名空间中,则可以使用globals()

dct = ['do_this', 'do_that']

getattr(my_module, dct[0])()

globals()[dct[0]]()

答案 3 :(得分:1)

在某些字典或类或实例中具有函数


def fn_a():
    pass

some_dict = {
    'fn_a': fn_a,
}

class Someclass(object):

  @classmethod
  def fn_a(cls):
    pass

  # normal instance method
  def fn_b(self):
    pass

some_instance = Someclass()

你可以这样做:some_dict['name']()getattr(some_instance, 'fn_b')()getattr(Someclass, 'fn_a')()

答案 4 :(得分:1)

如果您要调用的函数是模块的一部分:

import module
getattr(module, funcname_string)(*args, **kwargs)

答案 5 :(得分:1)

正如其他人所说,Python中的函数是一流的对象。如果您真的想从列表中获取其名称,可以使用eval()(不受欢迎)或使用globals()字典。请记住,如果这些字符串来自用户,则非常危险。如果他们不是来自用户,那么就不要使用字符串。

答案 6 :(得分:1)

def do_this(): pass
def do_that(): pass

dct = dict((x.__name__, x) for x in [do_this, do_that])
# dct maps function names to the function objects
# the names *don't* have to match the function name in your source:
#   dct = {"foo": do_this}
# which means user-facing names can be anything you want

dct["do_this"]()  # call do_this

答案 7 :(得分:0)

使用getattrs()

dct = ['do_this', 'do_that']


getattr(class_object, dct[0])()

您还可以通过

动态调用类中的函数
inspect.getmembers(my_class, predicate=inspect.ismethod)

然后执行for循环并调用getattr(class, methodname)

我认为使用getattr比使用globals()更适合大多数情况。 Globals()使用整个程序的全局名称空间范围,这可能会导致范围问题。

答案 8 :(得分:0)

要动态调用在同一模块中定义的函数,您可以这样做:

import sys

## get the reference to the current module - key trick to get the ref to same module
this = sys.modules[__name__]

def foo():
  msg="I'm called dynamically!"
  return msg

## `fname` can be taken as an input from the user
fname='foo'

## get the reference to the function from the module
fn = getattr(this, fname)

## make the function call
fn()