【问题标题】:Storing Functions in Dictionary [Python]在字典中存储函数 [Python]
【发布时间】:2015-05-28 11:52:08
【问题描述】:

我目前正在构建一个应用程序,在该应用程序中,我需要迭代一系列基本完成相同操作的步骤,只节省非常少量的代码(约 15 行)。步骤的数量会因项目的配置方式而异,因此为每个潜在实例创建单独的函数对我来说似乎有点愚蠢。

在 JavaScript 中,我会这样做:

var switches = [true, true, false, true];

var holder = {
    0: function() { /* do step0 */ }
    1: function() { /* do step1 */ }
    2: function() { /* do step2 */ }
    3: function() { /* do step3 */ }
    // ...etc...
}

for (var i = 0; i < switches.length; i++)
    if (switches[i])
        holder[i]();

有没有办法在 python 中做类似的事情?我唯一能想到的是这样的:

switches = [True, True, False, True]

class Holder(object):
    @staticmethod
    def do_0():
        # do step0

    @staticmethod
    def do_1():
        # do step 1

    # ...etc...

    def __repr__(self):
        return [self.do_0, self.do_1, ...]

for action in Holder:
    action()

如果我有大量的步骤,这似乎非常低效。有没有更好的方法来解决这个问题?

【问题讨论】:

  • 一个装饰器可能更符合你的要求
  • 最好的方法是什么?如果我使用相同的装饰器定义所有函数,是否有任何简单的方法来循环它们而不创建要循环的列表?

标签: javascript python arrays dictionary data-structures


【解决方案1】:

我通常会这样处理。 我喜欢这种方法,因为它给代码增加了最少的输入开销,而且如果您稍后编写额外的方法,则不需要在文件的其他地方进行任何修改。

def steptest0():
    code
def steptest1():
    code
def steptest2():
    code

...

tests = filter(lambda x: x.startswith('steptest'),
               dir())
for t in tests: eval(t + '()')

每个方法都已经在 Python 中自动放入字典中,dir() 让我们可以访问它。

免责声明。看到“eval”,普通行人狂热者的头脑中开始响起多个警钟,有些人甚至可能癫痫发作。让他们通过使用反射机制来保护自己免受 eval 的影响(这可能会降低其可读性,但仍然值得,因为他们不能被指责使用“eval”)。

【讨论】:

    【解决方案2】:

    看起来在 Python 中没有办法做到这一点,这是一个有意做出的设计决定,因为它被认为是非 Pythonic 的。哦,好吧,看起来我一直在定义方法,然后手动将它们添加到列表中以进行迭代。

    来源:https://softwareengineering.stackexchange.com/a/99245

    【讨论】:

      【解决方案3】:

      你可以这样做:

      # define your functions
      def fun1():
          print("fun1")
      
      def fun2():
          print("fun2")
      
      def fun3():
          print("fun3")
      
      
      switches = [True, False, True];
      
      # put them in a list (list makes more sense than dict based on your example)
      func_list = [fun1, fun2, fun3]
      
      # iterate over switches and corresponding functions, and execute 
      # functions when s is True    
      for s,f in zip(switches, func_list):
          if s: f() 
      

      这只是一种方式。还有很多其他的。例如根据需要使用 lambdas、dict 等。

      如果你的函数只有一行,要使用 lambdas,你可以这样做:

      func_list = [lambda: print("lambda1"), 
                   lambda: print("lambda2"), 
                   lambda: print("lambda1")]
      

      【讨论】:

      • 您的代码确实有效,但我试图避免在字典范围之外定义一堆函数。我可以使用我已经拥有的代码。不幸的是,我正在使用的代码比示例要复杂得多,如果不快速使代码变得不可读,我就无法真正定义一堆函数。
      • 我添加了 lambdas 示例。但是你不能把所有东西都放到 lambda 中。
      • Python 没有像 JS 这样的匿名函数。是的,有lambdas,但它们仅限于一个表达式。
      • 是的,如果 lambda 的限制少一点,那就太好了。不幸的是,对于一些更复杂的功能,我需要大约 15 行代码。
      • @RobertIngrum 所以你需要把它们分开。你可以用这些函数创建一个模块,或者像你一样创建一个类。
      【解决方案4】:
      - Your functions don't need to be enveloped in a utility class.
      - I don not see how the two blocks of code differ in efficiency.
      - You can use enumerate and lambdas to simplify your code.
      

      简化代码

      d = {0: lambda: 'Performing Step 0',
           1: lambda: 'Performing Step 1',
           2: lambda: 'Performing Step 2',
           3: lambda: 'Performing Step 3',
           4: lambda: 'Performing Step 4'}
      
      for index, switch in enumerate([1, 0, 1, 1, 0]):
          if switch == 1: d[index]() 
      

      【讨论】:

      • 我提供的例子被大大简化了。在我的实际示例中,Holder 类实际上只是一个帮助类,用于保存我的步进处理器的所有设置。起初我也考虑过使用 lambda,但看起来它们不能太复杂(即它们不适用于 15 行代码)。
      猜你喜欢
      • 2020-06-07
      • 2011-05-13
      • 1970-01-01
      • 1970-01-01
      • 2011-10-29
      • 2011-02-22
      • 2013-05-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多