2015-03-24 82 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」)。