2016-09-04 5 views
1

diesen Code Gegeben:Wechselsteuerfluss mit conditionals oder Präprozessor

for i in range(5): 
    foo(i) 
    bar(i) 

Ich möchte einige Code zwischen den beiden print Linien so hinzufügen, dass ich die Schleife in zwei brechen kann, aber nur, wenn eine bestimmte Flagge gilt , dh:

for i in range(5): 
    foo(i) 

if debug: { 
    continue 
for i in range(5): 
} 

    bar(i) 

Leider ist dies nicht Python gültig. Gibt es eine Möglichkeit das ich tun kann, dass ohne manuell die Schleife zu umschreiben:

if debug: 
    for i in range(5): 
    foo(i) 
    for i in range(5): 
    bar(i) 
else: 
    for i in range(5): 
    foo(i) 
    bar(i) 
+2

Nein, es gibt keine Präprozessor in Python, so dass Sie keine Äquivalent von Prä-Prozessor-Stil-Richtlinien verwenden. Kannst du mehr Details oder konkreteres Beispiel teilen? Im Moment riecht es nach [XY Problem] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) - sagen Sie uns was Sie tun möchten, nicht _how_ Sie wollen es tun . –

+0

@ ŁukaszRogalski Danke. Das obige ist genau das, was ich versuche zu tun. Ich suche nach einer Möglichkeit, die Schleife zu unterbrechen, ohne die Argumente zu 'foo' und' bar' zu ändern oder die Körper dieser Funktionen zu ändern. – JRR

+1

Können Sie erklären, warum Sie dies ein wenig mehr tun möchten, vielleicht ein wenig mehr Kontext hinzufügen und was die Funktionen tun? –

Antwort

0

Wenn ich richtig verstehe, Sie wollen entweder die Anruffunktionen in Chargen (alle möglichen Argumente für die erste Funktion, dann werden alle möglichen Argumente für die zweite Funktion in ersten Fall usw.) und Argumente in Chargen in zweiten Fall (also alle Funktion für die erste arg, dann werden alle Funktionen für die zweite arg etc.)

würde ich sagen Sie es explizit zu tun haben:

def foo(i): 
    print("foo", i) 

def bar(i): 
    print("bar", i) 

def stretch(seq, n): 
    """stretch([1,2,3], 3) -> [1,1,1,2,2,2,3,3,3], lazy generator""" 
    for o in seq: 
     for _ in range(n): 
      yield o 


def run(args, functions, mode): 
    if mode: 
     my_args = list(stretch(args, len(functions))) 
     my_functions = functions * len(args) 
    else: 
     my_args = args * len(functions) 
     my_functions = list(stretch(functions, len(args))) 
    for f, a in zip(my_functions, my_args): 
     f(a) 

Invokation:

run(list(range(5)), [foo, bar], 0) 

Ausgang:

foo 0 
foo 1 
foo 2 
foo 3 
foo 4 
bar 0 
bar 1 
bar 2 
bar 3 
bar 4 

Invocation:

run(list(range(5)), [foo, bar], 1) 

Ausgang:

foo 0 
bar 0 
foo 1 
bar 1 
foo 2 
bar 2 
foo 3 
bar 3 
foo 4 
bar 4 

Hier ist, was wir haben, ist getan, dass wir Paare für (callable, argument_to_callable) erstellt, wenn bestimmt, um durch Ihre Anforderung. Also im Wesentlichen haben Sie einen Booleschen, der "eine Art" für Sie eine Schleife dupliziert hat.

Code ist irgendwie hässlich, ich frage mich, ob jemand mit einer besseren Lösung kommt.

-1

Präprozessor-Derivate ändern Ihren Code, bevor er überhaupt ausgeführt werden kann. In der C-Familie von Sprachen beispielsweise ersetzt der Compiler alle Ausdrücke innerhalb von preprocessor Blöcken vor der Kompilierung.

In Ihrem Beispiel ist debug eine Laufzeitvariable, daher können Sie die Struktur Ihres Codes basierend auf dieser Variablen nicht ändern. Zumindest nicht in Python.

Allerdings gibt es immer (gut, fast immer) eine Möglichkeit, die Sie vermeiden können, etwas manuell zu tun. In dem gleichen Sinn wie echte Präprozessorblöcke, die den Code ändern, bevor er ausgeführt wird, müssen wir eine Ebene höher gehen und Inhalt hinzufügen, bevor der Code ausgeführt wird. Die einfachste Möglichkeit besteht darin, den Code als Zeichenfolge zu bearbeiten und die Zeichenfolge während der Ausführung zu ändern. Ich werde nicht genug betonen, wie unpythonisch dieses erfundene Beispiel ist, aber mit exec können Sie den Code injizieren, den Sie wollen. Die Lösung wird immer funktionieren, egal welche Funktion Sie verwenden. Hier geht es:

Zunächst definieren Sie Ihre Debug-Flag

if_debug = "" 
if debug: 
    if_debug = "continue\nfor i in range(5):\n " 

Schließlich wickeln Sie den Code innerhalb eines exec("") Block.Die String-Substitution findet statt, bevor der Code zur Auswertung an den Interpreter gesendet wird.

Es gibt Makrobibliotheken, mit denen Sie die Interpretation Ihres Codes ändern können. Sehen Sie sich zum Beispiel MacroPy an.

+0

Ich sehe nicht, warum dies nach unten geht. Er beantwortet die vom OP gestellte Frage. – dangom

0

Hmmm können wir immer

mitten in der Luft Ergebnis in der Liste speichern
n = range(10) 
if debug: 
    n = list(map(lambda x: foo(x),n))+list(map(lambda x: bar(x),n)) 
else: 
    n = list(map(lambda x: [foo(x),bar(x)],n))