2010-08-19 11 views
48

Si tengo un objeto y un nombre de método en una cadena, ¿cómo puedo llamar al método?Llamar a un método de Python por nombre

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

def callMethod(o, name): 
    ??? 

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

Aunque son similares, esto no es un duplicado exacto de [esta cuestión] (http://stackoverflow.com/questions/3061/calling-a-function-from -a-string-with-the-functions-name-in-python), que pregunta acerca de una función en un módulo, en lugar de un método de un objeto. – Grumdrig

Respuesta

73

fácil:

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

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


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

Tome un vistazo a getattr

También puede utilizar setattr para establecer los atributos de clase de nombres.

+0

¡No pude encontrar qué buscar en la documentación! ¡Gracias! – Jazz

+0

@Jazz, está bajo construcciones internas. Es posible que tenga que hacer una búsqueda en la página con 'C-f' – aaronasterling

+0

De nada. –

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

No es necesario crear una instancia de Foo first!

+0

¡Fue solo un ejemplo, tengo una instancia real de una clase real! – Jazz

+2

Llamar a un método de una clase no inicializada puede implicar que estás haciendo algo mal. –

+0

¿Qué pasa si 'foo' no está en globos globales? – aaronasterling

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

Tenía una pregunta similar, quería llamar al método de instancia por referencia. Aquí hay cosas divertidas que encontré:

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 es increíble!

0

Aquí hay una versión más generalizada que utiliza decoradores de Python. Puede llamar por nombre corto o largo. Lo encontré útil al implementar CLI con subcomandos cortos y largos.

Los decoradores de Python son maravillosos. Bruce Eckel (Thinking in Java) describe aquí a los decoradores de Python.

http://www.artima.com/weblogs/viewpost.jsp?thread=240808 http://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') 
Cuestiones relacionadas