2015-03-24 63 views
8

我目前正在构建一个应用程序,我需要遍历一系列完成相同事情的步骤,保存非常少量的代码(〜15行)。步骤的数量取决于项目的配置方式,因此对于我为每个潜在实例创建一个单独的函数似乎很愚蠢。在字典中存储函数[Python]

在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() 

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

+0

装饰者可能更符合你想要的 – 2015-03-25 00:40:08

+0

这样做最好的方法是什么?如果我使用相同的装饰器定义所有的函数,是否有任何简单的方法循环遍历它们,而不需要创建一个循环列表? – 2015-03-25 01:04:38

回答

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() 

这只是一种方式。还有很多其他的。例如使用lambda表达式,如字典你想等

要使用lambda表达式,如果你的函数只有一条线,你可以这样做:

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

你的代码绝对可行,但我试图避免在字典范围之外定义一堆函数。我可以只使用我已有的代码。 不幸的是,我正在使用的代码比这个例子复杂得多,而且如果不快速使代码无法读取,我无法真正定义一堆函数。 – 2015-03-25 00:02:51

+1

我添加了lambda示例。但是你不能把所有东西都放入lambda的。 – Marcin 2015-03-25 00:04:03

+2

Python没有像JS这样的匿名函数。是的,有['''lambda'''](https://docs.python.org/2/tutorial/controlflow.html#lambda-expressions),但它们仅限于一个表达式。 – pzp 2015-03-25 00:06:17

1
- 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]() 
+0

我提供的例子大大简化了。在我的实际示例中,Holder类实际上只是一个辅助类,用于保存步进处理器的所有设置。我还首先研究了使用lambda表达式,但看起来他们不能太复杂(即它们不适用于15行代码)。 – 2015-03-25 00:06:09

-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”)。