2015-03-24 6 views
8

Ich bin gerade dabei, eine Anwendung zu erstellen, wo ich über eine Reihe von Schritten, die weitgehend die gleiche Sache, eine sehr kleine Menge Code (~ 15 Zeilen) speichern müssen. Die Anzahl der Schritte hängt davon ab, wie das Projekt konfiguriert ist. Daher erscheint es mir ziemlich albern, für jede mögliche Instanz eine separate Funktion zu erstellen. Speichern von Funktionen in Dictionary [Python]

In JavaScript, würde ich so etwas tun:

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

Gibt es eine Möglichkeit etwas ähnliches wie dies in Python zu tun? Das einzige, was ich mir vorstellen kann, ist etwa folgendes:

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

Dies scheint nur schrecklich ineffizient, wenn ich eine signifikante Anzahl von Schritten habe. Gibt es einen besseren Weg, dies zu tun?

+0

Ein Dekorateur passt besser zu dem, was Sie wollen –

+0

Was wäre der beste Weg, dies zu tun? Wenn ich alle Funktionen mit demselben Dekorator definiere, gibt es eine einfache Möglichkeit, sie zu durchlaufen, ohne eine Liste zum Durchlaufen zu erstellen? –

Antwort

2

Es sieht Es gibt keine Möglichkeit, dies in Python zu tun, eine Designentscheidung, die absichtlich getroffen wurde, da sie als unpythonisch abgetan wurde. Naja, es sieht so aus, als ob ich die Methoden definiere und sie manuell zu einer Liste hinzufüge, um sie zu durchlaufen.

Quelle: https://softwareengineering.stackexchange.com/a/99245

3

Sie können dies wie folgt:

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

Dies ist nur eine Möglichkeit. Es gibt viele andere. z.B. mit Lambda-Ausdrücke, dict, wie man wollte, usw.

lambdas zu verwenden, wenn Ihre Funktionen nur eine Zeile sind, können Sie tun:

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

Ihr Code funktioniert definitiv, aber ich versuche, eine Reihe von Funktionen außerhalb des Wörterbuchbereichs zu definieren. Ich könnte einfach den Code verwenden, den ich sonst schon habe. Leider ist der Code, mit dem ich arbeite, ein wenig komplizierter als das Beispiel, und ich konnte nicht wirklich eine Reihe von Funktionen definieren, ohne den Code schnell unlesbar zu machen. –

+1

Ich habe lambdas Beispiel hinzugefügt. Aber Sie können nicht alles in Lambda's setzen. – Marcin

+2

Python hat keine anonymen Funktionen wie JS. Ja, es gibt ['' 'lambda'''] (https://docs.python.org/2/tutorial/controlflow.html#lambda-expressions), diese sind jedoch auf einen einzelnen Ausdruck beschränkt. – pzp

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. 

Vereinfachte-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

Das von mir bereitgestellte Beispiel ist stark vereinfacht. In meinem aktuellen Beispiel ist die Holder-Klasse eigentlich nur eine Hilfsklasse, die alle Einstellungen für meinen Schrittprozessor enthält. Ich habe auch zuerst die Verwendung von Lambda untersucht, aber es sieht so aus, als könnten sie nicht zu kompliziert sein (d. H., Sie funktionieren nicht für 15 Zeilen Code). –

-1

ich in der Regel darüber, wie die folgenden gehen. Ich mag diesen Ansatz, weil er dem Code ein Minimum an Tippaufwand hinzufügt, und wenn Sie später eine zusätzliche Methode schreiben, muss an keiner anderen Stelle in der Datei etwas geändert werden.

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

... 

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

Jede Methode wird bereits in einem Wörterbuch automatisch in Python setzen, und dir() lässt uns, dass zugreifen.

Haftungsausschluss. Es gibt mehrere Alarmglocken, die bei dem Anblick von "eval" im Kopf des durchschnittlichen Fußgaenger-Eiferers beginnen und einige sogar Anfälle haben. Lassen Sie sie sich vor Eval schützen, indem Sie stattdessen einen Reflektionsmechanismus verwenden (der sie vielleicht weniger lesbar macht, aber immer noch wert ist, da sie nicht beschuldigt werden können, "eval" zu verwenden).