代码之家  ›  专栏  ›  技术社区  ›  Jazz

按名称调用python方法

  •  60
  • Jazz  · 技术社区  · 16 年前

    如果在字符串中有一个对象和一个方法名,如何调用该方法?

    class Foo:
        def bar1(self):
            print 1
        def bar2(self):
            print 2
    
    def callMethod(o, name):
        ???
    
    f = Foo()
    callMethod(f, "bar1")
    
    5 回复  |  直到 9 年前
        1
  •  88
  •   Enrico Carlesso    16 年前

    简单一:

    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 用于按名称设置类属性。

        2
  •  5
  •   Yaroslav Stavnichiy    13 年前

    我有类似的问题,想通过引用调用实例方法。以下是我发现的一些有趣的事情:

    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
    

    巨蟒太神奇了!

        3
  •  2
  •   Björn    16 年前
    getattr(globals()['Foo'](), 'bar1')()
    getattr(globals()['Foo'](), 'bar2')()
    

    不需要先实例化foo!

        4
  •  1
  •   Htechno    16 年前
    def callmethod(cls, mtd_name):    
        method = getattr(cls, mtd_name)
        method()
    
        5
  •  0
  •   Nitin Muppalaneni    9 年前

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

    巨蟒装饰师真是太棒了。Bruce Eckel(在爪哇思考)在这里描述了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')