【问题标题】:Call a Python method by name按名称调用 Python 方法
【发布时间】:2021-05-28 15:50:40
【问题描述】:

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

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

def callMethod(o, name):
    ???

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

【问题讨论】:

标签: python


【解决方案1】:

使用内置的getattr()函数:

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

def call_method(o, name):
    return getattr(o, name)()


f = Foo()
call_method(f, "bar1")  # prints 1

您还可以使用setattr() 按名称设置类属性。

【讨论】:

  • 我在文档中找不到要搜索的内容!谢谢!
  • @Jazz,它在内置插件下。您可能需要使用 C-f 进行页内搜索
  • @aaronasterling 我知道,但我找不到要搜索的词!
  • 为什么 callMethod(f, "bar1") 不被调用 f.callMethod(f, "bar1")
  • PhilipJ,因为它只是前面几行定义的方法,在 Foo: 类之外。
【解决方案2】:
getattr(globals()['Foo'](), 'bar1')()
getattr(globals()['Foo'](), 'bar2')()

无需先实例化 Foo!

【讨论】:

  • 这只是一个例子,我有一个真实类的真实实例!
  • 调用未初始化类的方法可能意味着你做错了什么。
  • 如果foo 不在全局变量中怎么办?
  • 它可能不是,但你应该注意Foo 是。 ;)
【解决方案3】:
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是惊人的!

    【讨论】:

      【解决方案5】:

      这是一个使用 Python 装饰器的更通用的版本。您可以使用短名称或长名称呼叫。我发现在使用短子命令和长子命令实现 CLI 时它很有用。

      Python 装饰器很棒。 Bruce Eckel(Thinking in Java)在这里很好地描述了 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')
      

      【讨论】:

        猜你喜欢
        • 2012-02-16
        • 2012-11-28
        • 2010-11-08
        • 2011-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多