2010-08-19 78 views
48

如果我在字符串中有对象和方法名称,该如何调用该方法?按名称调用Python方法

class Foo: 
    def bar1(self): 
     print 1 
    def bar2(self): 
     print 2 

def callMethod(o, name): 
    ??? 

f = Foo() 
callMethod(f, "bar1") 
+1

虽然它们是相似的,这不是[这个问题](完全重复http://stackoverflow.com/questions/3061/calling-a-function-from -a-string-with-the-functions-name-in-python),它询问模块中的函数,而不是对象的方法。 – Grumdrig 2012-12-12 20:07:42

回答

73

轻松一:

class Foo: 
    def bar1(self): 
     print 1 
    def bar2(self): 
     print 2 

def callMethod(o, name): 
    getattr(o, name)() 


f = Foo() 
callMethod(f, "bar1") 

看看getattr

您还可以使用setattr设置类的名称属性。

+0

我无法在文档中找到要搜索的内容!谢谢! – Jazz 2010-08-19 12:37:15

+0

@Jazz,它在内置。您可能必须使用“C-f”进行页内搜索。 – aaronasterling 2010-08-19 12:38:52

+0

不客气。 – 2010-08-19 12:38:57

2
getattr(globals()['Foo'](), 'bar1')() 
getattr(globals()['Foo'](), 'bar2')() 

不需要先实例化Foo!

+0

这只是一个例子,我有一个真正的课堂的实例! – Jazz 2010-08-19 12:35:59

+2

调用一个未初始化的类的方法可能意味着你做错了什么。 – 2010-08-19 12:38:39

+0

如果'foo'不是全局变量? – aaronasterling 2010-08-19 12:39:43

1
def callmethod(cls, mtd_name):  
    method = getattr(cls, mtd_name) 
    method() 
4

我有类似的问题,想通过引用来调用实例方法。这里有我发现的有趣的东西:

instance_of_foo=Foo() 

method_ref=getattr(Foo, 'bar') 
method_ref(instance_of_foo) # instance_of_foo becomes self 

instance_method_ref=getattr(instance_of_foo, 'bar') 
instance_method_ref() # instance_of_foo already bound into reference 

Python是惊人的!

0

这是一个使用Python装饰器的更通用的版本。您可以通过短名或长名打电话。在使用短和长子命令执行CLI时,我发现它很有用。

Python装饰者是美好的。 Bruce Eckel(Thinking in Java)在这里很好地描述了Python装饰器。

http://www.artima.com/weblogs/viewpost.jsp?thread=240808http://www.artima.com/weblogs/viewpost.jsp?thread=240845

#!/usr/bin/env python2 

from functools import wraps 


class CommandInfo(object): 
    cmds = [] 

    def __init__(self, shortname, longname, func): 
     self.shortname = shortname 
     self.longname = longname 
     self.func = func 


class CommandDispatch(object): 
    def __init__(self, shortname, longname): 
     self.shortname = shortname 
     self.longname = longname 

    def __call__(self, func): 
     print("hello from CommandDispatch's __call__") 

     @wraps(func) 
     def wrapped_func(wself, *args, **kwargs): 
      print('hello from wrapped_func, args:{0}, kwargs: {1}'.format(args, kwargs)) 
      func(wself, *args, **kwargs) 

     ci = CommandInfo 
     ci.cmds += [ci(shortname=self.shortname, longname=self.longname, func=func)] 
     return wrapped_func 

    @staticmethod 
    def func(name): 
     print('hello from CommandDispatch.func') 

     for ci in CommandInfo.cmds: 
      if ci.shortname == name or ci.longname == name: 
       return ci.func 

     raise RuntimeError('unknown command') 


@CommandDispatch(shortname='co', longname='commit') 
def commit(msg): 
    print('commit msg: {}'.format(msg)) 


commit('sample commit msg')   # Normal call by function name 

cd = CommandDispatch 
short_f = cd.func(name='co')  # Call by shortname 
short_f('short sample commit msg') 

long_f = cd.func(name='commit')  # Call by longname 
long_f('long sample commit msg') 


class A(object): 
    @CommandDispatch(shortname='Aa', longname='classAmethoda') 
    def a(self, msg): 
     print('A.a called, msg: {}'.format(msg)) 


a = A() 
short_fA = cd.func(name='Aa') 
short_fA(a, 'short A.a msg') 

long_fA = cd.func(name='classAmethoda') 
long_fA(a, 'short A.a msg')