csdnceshi52
妄徒之命
采纳率25%
2008-08-06 03:36 阅读 161

使用函数名(字符串)调用模块的函数

What is the best way to go about calling a function given a string with the function's name in a Python program. For example, let's say that I have a module foo, and I have a string whose contents are "bar". What is the best way to go about calling foo.bar()?

I need to get the return value of the function, which is why I don't just use eval. I figured out how to do it by using eval to define a temp function that returns the result of that function call, but I'm hoping that there is a more elegant way to do this.

转载于:https://stackoverflow.com/questions/3061/calling-a-function-of-a-module-by-using-its-name-a-string

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

10条回答 默认 最新

  • 已采纳
    csdnceshi61 derek5. 2008-08-06 03:57

    Assuming module foo with method bar:

    import foo
    method_to_call = getattr(foo, 'bar')
    result = method_to_call()
    

    As far as that goes, lines 2 and 3 can be compressed to:

    result = getattr(foo, 'bar')()
    

    if that makes more sense for your use case. You can use getattr in this fashion on class instance bound methods, module-level methods, class methods... the list goes on.

    点赞 30 评论 复制链接分享
  • csdnceshi68 local-host 2008-08-07 11:35

    Patrick's solution is probably the cleanest. If you need to dynamically pick up the module as well, you can import it like:

    module = __import__('foo')
    func = getattr(module, 'bar')
    func()
    
    点赞 26 评论 复制链接分享
  • csdnceshi66 必承其重 | 欲带皇冠 2009-05-07 12:45
    locals()["myfunction"]()
    

    or

    globals()["myfunction"]()
    

    locals returns a dictionary with a current local symbol table. globals returns a dictionary with global symbol table.

    点赞 25 评论 复制链接分享
  • weixin_41568127 ?yb? 2016-10-24 13:20

    The best answer according to the Python programming FAQ would be:

    functions = {'myfoo': foo.bar}
    
    mystring = 'myfoo'
    if mystring in functions:
        functions[mystring]()
    

    The primary advantage of this technique is that the strings do not need to match the names of the functions. This is also the primary technique used to emulate a case construct

    点赞 9 评论 复制链接分享
  • csdnceshi78 程序go 2012-08-19 09:40

    Just a simple contribution. If the class that we need to instance is in the same file, we can use something like this:

    # Get class from globals and create an instance
    m = globals()['our_class']()
    
    # Get the function (from the instance) that we need to call
    func = getattr(m, 'function_name')
    
    # Call it
    func()
    

    For example:

    class A:
        def __init__(self):
            pass
    
        def sampleFunc(self, arg):
            print('you called sampleFunc({})'.format(arg))
    
    m = globals()['A']()
    func = getattr(m, 'sampleFunc')
    func('sample arg')
    
    # Sample, all on one line
    getattr(globals()['A'](), 'sampleFunc')('sample arg')
    

    And, if not a class:

    def sampleFunc(arg):
        print('you called sampleFunc({})'.format(arg))
    
    globals()['sampleFunc']('sample arg')
    
    点赞 7 评论 复制链接分享
  • csdnceshi67 bug^君 2012-12-28 16:56

    none of what was suggested helped me. I did discover this though.

    <object>.__getattribute__(<string name>)(<params>)
    

    I am using python 2.66

    Hope this helps

    点赞 6 评论 复制链接分享
  • csdnceshi73 喵-见缝插针 2013-10-16 00:24

    Given a string, with a complete python path to a function, this is how I went about getting the result of said function:

    import importlib
    function_string = 'mypackage.mymodule.myfunc'
    mod_name, func_name = function_string.rsplit('.',1)
    mod = importlib.import_module(mod_name)
    func = getattr(mod, func_name)
    result = func()
    
    点赞 6 评论 复制链接分享
  • csdnceshi67 bug^君 2014-04-09 10:17

    The answer (I hope) no one ever wanted

    Eval like behavior

    getattr(locals().get("foo") or globals().get("foo"), "bar")()
    

    Why not add auto-importing

    getattr(
        locals().get("foo") or 
        globals().get("foo") or
        __import__("foo"), 
    "bar")()
    

    In case we have extra dictionaries we want to check

    getattr(next((x for x in (f("foo") for f in 
                              [locals().get, globals().get, 
                               self.__dict__.get, __import__]) 
                  if x)),
    "bar")()
    

    We need to go deeper

    getattr(next((x for x in (f("foo") for f in 
                  ([locals().get, globals().get, self.__dict__.get] +
                   [d.get for d in (list(dd.values()) for dd in 
                                    [locals(),globals(),self.__dict__]
                                    if isinstance(dd,dict))
                    if isinstance(d,dict)] + 
                   [__import__])) 
            if x)),
    "bar")()
    
    点赞 6 评论 复制链接分享
  • csdnceshi67 bug^君 2012-02-14 05:55

    For what it's worth, if you needed to pass the function (or class) name and app name as a string, then you could do this:

    myFnName  = "MyFn"
    myAppName = "MyApp"
    app = sys.modules[myAppName]
    fn  = getattr(app,myFnName)
    
    点赞 4 评论 复制链接分享
  • csdnceshi53 Lotus@ 2016-12-07 18:29

    Try this. While this still uses eval, it only uses it to summon the function from the current context. Then, you have the real function to use as you wish.

    The main benefit for me from this is that you will get any eval-related errors at the point of summoning the function. Then you will get only the function-related errors when you call.

    def say_hello(name):
        print 'Hello {}!'.format(name)
    
    # get the function by name
    method_name = 'say_hello'
    method = eval(method_name)
    
    # call it like a regular function later
    args = ['friend']
    kwargs = {}
    method(*args, **kwargs)
    
    点赞 1 评论 复制链接分享

相关推荐