问题:通过使用模块名称(字符串)来调用模块的功能

在Python程序中,给定带有函数名称的字符串的最佳方法是什么?例如,假设我有一个模块foo,我有一个内容为的字符串"bar"。最好的通话方式是foo.bar()什么?

我需要获取函数的返回值,这就是为什么我不只是使用eval。我想出了如何通过eval定义一个临时函数来返回该函数调用的结果的方法,但是我希望有一种更优雅的方法。

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 content is "bar". What is the best way to call 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.


回答 0

假设模块foo与方法bar

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

您可以将第2行和第3行缩短为:

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

如果这对您的用例更有意义。

您可以通过getattr这种方式在类实例绑定的方法,模块级方法,类方法…上使用清单。

Assuming module foo with method bar:

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

You could shorten lines 2 and 3 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.


回答 1

locals()["myfunction"]()

要么

globals()["myfunction"]()

locals返回带有当前本地符号表的字典。globals返回带有全局符号表的字典。

locals()["myfunction"]()

or

globals()["myfunction"]()

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


回答 2

帕特里克(Patrick)的解决方案可能是最干净的。如果您还需要动态提取模块,则可以按以下方式导入它:

module = __import__('foo')
func = getattr(module, 'bar')
func()

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()

回答 3

只是一个简单的贡献。如果我们需要实例化的类在同一文件中,则可以使用类似以下内容的东西:

# 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()

例如:

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')

而且,如果不是类:

def sampleFunc(arg):
    print('you called sampleFunc({})'.format(arg))

globals()['sampleFunc']('sample arg')

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')

回答 4

给定一个字符串,带有指向函数的完整python路径,这就是我如何获取所述函数的结果:

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()

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()

回答 5

根据Python编程常见问题解答,最佳答案是:

functions = {'myfoo': foo.bar}

mystring = 'myfoo'
if mystring in functions:
    functions[mystring]()

该技术的主要优点是字符串不需要与函数名称匹配。这也是用于模拟案例构造的主要技术

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


回答 6

答案(我希望)没有人想要

评估行为

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

为什么不添加自动导入

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

如果我们有额外的字典,我们要检查

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

我们需要更深入

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")()

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")()

回答 7

对于它的价值,如果您需要将函数(或类)名称和应用名称作为字符串传递,则可以执行以下操作:

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)

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)

回答 8

尝试这个。尽管此方法仍使用eval,但仅使用它从当前上下文中调用函数。这样,您便可以根据需要使用实际功能。

这对我的主要好处是,在调用该函数时,您将得到与评估有关的所有错误。这样,您在调用时将获得与功能相关的错误。

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)

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)

回答 9

建议的内容都没有帮助我。我确实发现了这一点。

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

我正在使用python 2.66

希望这可以帮助

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


回答 10

就像这个问题一样,如何使用方法名称分配给变量[duplicate]来动态调用类中的方法,这个变量被标记为重复变量,我在这里发布了一个相关的答案:

场景是,一个类中的一个方法想动态调用同一类上的另一个方法,我在原始示例中添加了一些细节,从而提供了更广泛的场景和清晰度:

class MyClass:
    def __init__(self, i):
        self.i = i

    def get(self):
        func = getattr(MyClass, 'function{}'.format(self.i))
        func(self, 12)   # This one will work
        # self.func(12)    # But this does NOT work.


    def function1(self, p1):
        print('function1: {}'.format(p1))
        # do other stuff

    def function2(self, p1):
        print('function2: {}'.format(p1))
        # do other stuff


if __name__ == "__main__":
    class1 = MyClass(1)
    class1.get()
    class2 = MyClass(2)
    class2.get()

输出(Python 3.7.x)

功能1:12

功能2:12

As this question How to dynamically call methods within a class using method-name assignment to a variable [duplicate] marked as a duplicate as this one, I am posting a related answer here:

The scenario is, a method in a class want to call another method on the same class dynamically, I have added some details to original example which offers some wider scenario and clarity:

class MyClass:
    def __init__(self, i):
        self.i = i

    def get(self):
        func = getattr(MyClass, 'function{}'.format(self.i))
        func(self, 12)   # This one will work
        # self.func(12)    # But this does NOT work.


    def function1(self, p1):
        print('function1: {}'.format(p1))
        # do other stuff

    def function2(self, p1):
        print('function2: {}'.format(p1))
        # do other stuff


if __name__ == "__main__":
    class1 = MyClass(1)
    class1.get()
    class2 = MyClass(2)
    class2.get()

Output (Python 3.7.x)

function1: 12

function2: 12


回答 11

这是一个简单的答案,例如,这将使您可以清除屏幕。下面有两个示例,分别是eval和exec,它们在清理后将在顶部显示0(如果使用Windows,请更改clearcls,例如Linux和Mac用户将按原样离开)或仅执行它。

eval("os.system(\"clear\")")
exec("os.system(\"clear\")")

This is a simple answer, this will allow you to clear the screen for example. There are two examples below, with eval and exec, that will print 0 at the top after cleaning (if you’re using Windows, change clear to cls, Linux and Mac users leave as is for example) or just execute it, respectively.

eval("os.system(\"clear\")")
exec("os.system(\"clear\")")

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。