2009-08-14 7 views
33

Dieses Problem beschäftigt mich schon seit einiger Zeit. Gibt es einen einfacheren Weg verschachtelte for Schleifen in Python zu schreiben? Zum Beispiel, wenn mein Code geht dies so etwas wie:In Python gibt es eine einfachere Möglichkeit, 6 verschachtelte For-Schleifen zu schreiben?

for y in range(3): 
    for x in range(3): 
     do_something() 
     for y1 in range(3): 
     for x1 in range(3): 
      do_something_else() 

wäre es ein einfacher Weg, dies zu tun? Ich weiß, dass dieser Code funktioniert, aber wenn Sie einrücken, anstatt 2 Leerzeichen zu verwenden, wie ich, kann es ein Problem werden.

Oh im Beispiel gab es nur 4 verschachtelte for Schleifen, um die Dinge einfacher zu machen.

+0

[Siehe auch.] (Http://stackoverflow.com/a/533917/1430829) –

Antwort

53

map() verwenden Wenn Sie Wenn Sie häufig über ein kartesisches Produkt iterieren, wie in Ihrem Beispiel, möchten Sie vielleicht Python 2.6's itertools.product untersuchen - oder schreiben Sie Ihr eigenes, wenn Sie in einem früheren Python sind.

from itertools import product 
for y, x in product(range(3), repeat=2): 
    do_something() 
    for y1, x1 in product(range(3), repeat=2): 
    do_something_else() 
+0

Wenn geschachtelt Schleife wie folgt: ' '' für y im Bereich (3): do_something1() für x im Bereich (3): do_something() '' 'Wie kann ich das Produkt verwenden –

+0

@ ErtuğrulAltınboğa Ohne Eindruck ist es unmöglich zu sagen, was Sie versuchen zu tun Ich schlage vor, eine neue StackOverflow-Frage zu stellen, anstatt zu versuchen, Hilfe in Kommentaren zu bekommen. –

9

Wenn ich mit dieser Art von Programmlogik konfrontiert bin, würde ich wahrscheinlich die Reihenfolge der Schleifen in zwei oder mehr separate Funktionen aufteilen.

Eine andere Technik in Python ist es, wo möglich statt einer Schleife list comprehensions zu verwenden.

2

Mein persönliches Argument wäre, dass Sie wahrscheinlich etwas falsch machen, wenn Sie 6 verschachtelte Schleifen haben ...

Das heißt, funktionelle Zersetzung ist das, was Sie suchen. Refactor, so dass einige der Schleifen in separaten Funktionsaufrufen auftreten, dann rufen Sie diese Funktionen auf.

+2

Hier ist der Anwendungsfall, in dem ich zuletzt so viele verschachtelte Loops hatte: Stellen Sie sich vor, Sie würden einen 3D Gauss'schen "Unschärfe" -Filter auf ein 3D anwenden Datensatz; Sie haben Summierungen in alle drei Richtungen für den Filter (3 Schleifen) und Iterieren über jeden Punkt in drei Richtungen, um ihn anzuwenden (3 weitere Schleifen). Oh, und die Daten, die ich filterte, waren Geschwindigkeiten, also gab es drei Komponenten, die durchlaufen werden mussten (1 letzte Schleife). –

6

jede Schleife Unter der Annahme hat, eine Art unabhängige Bedeutung haben, brechen sie in benannte Funktionen aus:

def do_tigers(): 
    for x in range(3): 
     print something 

def do_lions(): 
    do_lionesses() 
    for x in range(3): 
     do_tigers() 

def do_penguins(): 
    for x in range(3): 
     do_lions() 

..etc. 

ich vielleicht besser Namen gewählt haben könnte. 8-)

+3

Aww, keine Kätzchen :( –

+4

Ich würde die Löwinnen tun, wenn ich ein Löwe wäre. – Skurmedel

+3

Nun, das ist eine Möglichkeit, Kätzchen zu bekommen ... Obwohl, etwas größere als ich im Sinn hatte. –

1

So ziemlich unkompliziert und einfach aussieht. Willst du sagen, dass du auf mehrere Schichten von Schleifen verallgemeinern willst ... kannst du ein Beispiel aus dem wirklichen Leben geben?

Eine weitere Option, die ich denken könnte, wäre, eine Funktion zu verwenden, um die Parameter zu erzeugen und sie dann einfach in einer Schleife anwenden

def generate_params(n): 
    return itertools.product(range(n), range(n)) 

for x,y in generate_params(3): 
    do_something() 
4

Technisch könnte man itertools.product verwenden, um ein kartesisches Produkt von N-Sequenzen zu erhalten, und iterieren, dass:

for y, x, y1, x1 in itertools.product(range(3), repeat=4): 
    do_something_else() 

Aber ich glaube nicht, dass Sie tatsächlich gewinnt etwas Lesbarkeit weisen.

13

Dies ist ziemlich üblich, wenn mehrdimensionale Räume durchlaufen werden.Meine Lösung ist:

xy_grid = [(x, y) for x in range(3) for y in range(3)] 

for x, y in xy_grid: 
    # do something 
    for x1, y1 in xy_grid: 
     # do something else 
+0

Wenn Sie eine große Anzahl von Elementen durchlaufen haben, ist es besser, einen Generatorausdruck zu verwenden, zB 'xy_grid = ((x, y)) für x im Bereich (30000) für y im Bereich (30000)). – Garrett

2

aus dem Code sieht es aus wie Sie einen Vorgang mit jedem möglichen Punktepaar ausgeführt werden sollen, wobei x und y im Bereich 0..2.

, das zu tun:

for x1,y1,x2,y2 in itertools.product(range(3), repeat=4): 
    do_something_with_two_points(x1,y1,2,y2) 

Der Betrieb do_something_with_two_points wird 81 mal aufgerufen werden - einmal für jede mögliche Kombination von Punkten.

3

Python-Iteratoren, und insbesondere Generatoren, existieren genau, um das nette Refactoring von ansonsten komplizierten Schleifen zu ermöglichen. Natürlich ist es schwierig, aus einem einfachen Beispiel eine Abstraktion zu erhalten, aber vorausgesetzt, die 3 muss ein Parameter sein (vielleicht sollte das Ganze range(3) sein?), Und die zwei Funktionen, die Sie aufrufen, benötigen einige Parameter, die Loop-Variablen sind.

for y in range(3): 
    for x in range(3): 
     do_something(x, y) 
     for y1 in range(3): 
     for x1 in range(3): 
      do_something_else(x, y, x1, y1) 

in, zB:

def nestloop(n, *funcs): 
    head = funcs[0] 
    tail = funcs[1:] 
    for y in range(n): 
    for x in range(n): 
     yield head, x, y 
     if tail: 
     for subtup in nestloop(n, *tail): 
      yield subtup[:1] + (x, y) + subtup[1:] 

for funcandargs in nestloop(3, do_something, do_something_else): 
    funcandargs[0](*funcandargs[1:]) 

die genaue Art von Refactoring wird ohne Zweifel werden muß gezwickt für Ihre genauen Zwecke, aber den allgemeinen Punkt, dass Iteratoren (und in der Regel könnten Sie den Code Refactoring in der Tat nur einfache Generatoren) bieten sehr schöne Refactorings von Schleifen bleibt - all die Looping-Logi c geht in den Generator und der Code der Anwendungsebene wird mit einfachen for Schleifen und tatsächlicher anwendungsrelevanter Verarbeitung der in den for-Schleifen gewonnenen Elemente verlassen.

Verwandte Themen