【问题标题】:Call methods by string通过字符串调用方法
【发布时间】:2012-07-25 12:35:49
【问题描述】:

我有以下课程。

func_list= ["function1", "function2", "function3"]

class doit(object):
    def __init__(self):
        for item in func_list:
            if item == "function1":
                self.function1()
            elif item == "function2":
                self.function2()
            elif item == "function3":
                self.function3()

    def function1(self):
        #do this
        pass
    def function2(self):
        #do that
        pass
    def function3(self):
        pass

如果创建了此类的实例,它会遍历字符串列表并根据实际字符串调用方法。列表中的字符串具有相应方法的名称。

我怎样才能以更优雅的方式做到这一点? 我不想为添加到列表中的每个“功能”添加另一个 elif-path。

【问题讨论】:

  • 请注意,不要调用您的变量列表,因为它是 python 内置函数的名称。 funclistflist 之类的就可以了;)
  • 你应该把函数对象放在列表中,而不是strs中,然后调用每个对象。

标签: python python-2.5


【解决方案1】:
func_list= ["function1", "function2", "function3"]

class doit(object):
    def __init__(self):
        for item in func_list:
            getattr(self, item)()
    def function1(self):
        print "f1"
    def function2(self):
        print "f2"
    def function3(self):
        print "f3"



>>> doit()
f1
f2
f3

对于私有函数:

for item in func_list:
     if item.startswith('__'):
         getattr(self, '_' + self.__class__.__name__+ item)()
     else:
         getattr(self, item)()

.

getattr(object, name[, default])

返回对象的命名属性的值。名称必须是字符串。如果字符串是对象属性之一的名称,则结果是该属性的值。例如,getattr(x, 'foobar') 等价于 x.foobar。如果命名属性不存在,则返回默认值,否则引发 AttributeError。

http://docs.python.org/library/functions.html#getattr

【讨论】:

  • 如果您提到魔术是在 getattr 函数中完成并提供了文档链接,我认为这个答案会稍微好一些。
  • 去掉 list 变量也不错,因为它没有被使用。
  • @black_dragon:太好了,这就是我想做的。但是我如何访问private-方法如def __function4(self): print "private"
  • 私有函数 __function4 将作为 _doit__function4 访问,因为这就是名称被破坏以使其看起来是私有的方式。
  • @wewa 你应该避免__names。有关详细信息,请参阅stackoverflow.com/questions/165883/…。只需使用_names
【解决方案2】:

这通常通过字典查找来解决,因为函数是 Python 中的一等数据类型。例如:

# map string names to callable functions
dispatch = {'func1': func1, 'func2': func2, ...}

want_to_call = 'func1'
dispatch[want_to_call](args)

【讨论】:

    【解决方案3】:

    为什么不使用 lambda?

    比如说,

    def func1(a):
        return a ** 2
    
    def func2(a, b):
        return a ** 3 + b
    
    dic = {'Hello':lambda x: func1(x), 'World':lambda x,y: func2(x, y)} #Map functions to lambdas
    print dic['Hello'](3)
    print dic['World'](2,3)
    

    输出,9 11

    或者,你可以这样做......

    class funs():
        def func1(self, a):
            return a ** 2
    
        def func2(self, a, b):
            return a ** 3 + b
    
    f = funs()
    dic = {'Hello': lambda x: f.func1(x), 'World': lambda x,y: f.func2(x,y)}
    print dic['Hello'](3)
    print dic['World'](5,4)
    

    会给你,9 129

    【讨论】:

      【解决方案4】:
      class doit(object):
          def __init__(self, func_list):
              for func in func_list:
                  func(self)
          #insert other function definitions here
      
      func_list = [doit.function1, doit.function2, doit.function3]
      foo = doit(func_list)
      

      【讨论】:

        【解决方案5】:

        您可以使用 eval 让您的程序更简单、更简短。

        list= ["function1", "function2", "function3"]
        
        class doit(object):
            def __init__(self):
                for item in list:
                    eval(item)()
            def function1(self):
                print "f1"
            def function2(self):
                print "f2"
            def function3(self):
                    print "f3"
        

        【讨论】:

        • 使用exec 是另一种可能性。
        • -1,eval 和 exec 是永远不应该出现在 Python 代码中的东西。它们是安全漏洞,在这里完全是矫枉过正。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        • 2023-03-30
        • 2016-08-09
        相关资源
        最近更新 更多