2017-01-17 2 views
2

Versuchen Sie herauszufinden, wie diese parallele Zuweisung funktioniert. Der vollständige Code kann here gefunden werden. (Rohe Github-Python-Datei) Hier ist, was ich habe Probleme mit:Python Parallel Assignment

def assign_move(square): 

    # Parallel Assignment 
    target, direction = max(
     ((neighbor, direction) for direction, neighbor in enumerate(game_map.neighbors(square)) 
           if neighbor.owner != myID), 
           default = (None, None), 
           key = lambda t: t[0].production) 

ich es nach unten brechen würde so viel wie ich weiß, aber ich bin wahrscheinlich etwas falsch zu machen.

target, direction = max(iterable, default, key) 

Ordnen wir der gleichen Sache Ziel und Richtung zu? Ich dachte, parallel Zuordnung etwas wie x, y = 5, 6

Nun war, wenn wir an der iterable aussehen, ist es folgende:

iterable = ((neighbor, direction) for direction, neighbor in enumerate(game_map.neighbors(square)) if neighbor.owner != myID) 

Wie können wir (neighbor , direction) vor der for-Schleife haben? Was macht die if Aussage hier? Brauchen wir unter dem if-Block nichts, wenn neighbor.owner != myID?

Wenn der Iterator leer ist, geben wir None, None wie unten angezeigt zurück?

default = (None, None), 

Und das ist die Funktion, die wir verwenden, um das Maximum zu bestimmen?

key = lambda t: t[0].production) 

Hintergrund, wenn nötig: Dieser Code für ein Bot Halite im Spiel gespielt werden soll. Es ist ein vorgefertigter Bot, der in dieser GitHub repo gefunden wurde.

+1

Das ist keine 'for' Schleife mit einer' if' Anweisung; es ist ein [Listenverständnis mit einem Filter] (https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions) – Hamms

+0

Ahh perfekt! Ich hatte keine Ahnung, wonach ich überhaupt suchen sollte. – Loaf

+2

@Hamms: Genex, nicht LC. Keine eckigen Klammern. –

Antwort

1

Die max Funktion hier geben die maximale tuple von (direction , neighbors) in Bezug auf neighbor.production (wie wir dies von key verstehen) und Nachbarn in diesem Iterierte teilnehmen dürfen, wenn neighbor.owner != myID geschieht, und wenn Iterator default = (None, None) wird target und directions leer war sein Werte, so target ist die neighbor mit den meisten production am Ende.

+0

Wenn es "t [1] .production" wäre, wäre es "direction.production"? – Loaf

+1

Ja, nehme an, t ist hier dein 'Tupel', also ist das erste Element' neighbor' und das zweite ist 'direction' und es wird kein Fehler zurückgegeben, wenn' direction' Klasse ein 'production' Member hat. – Arman

+1

Perfekt! Danke für die Erklärung. Das macht viel mehr Sinn mit der Erkenntnis, dass 'for' und' if' nicht eine for-Schleife oder eine if/else-Anweisung ist. – Loaf

1

Immer wenn mehrere Variablen links von einer Zuweisung vorhanden sind, muss die rechte Seite eine Sequenz mit genau so vielen Elementen sein, die in die einzelnen Variablen entpackt werden.

Manchmal baut die rechte Seite diese Sequenz explizit auf: zum Beispiel ist x, y = 5, 6 technisch die Konstruktion des Tupels (5, 6), gefolgt von seinem Entpacken. (Tatsächlich wird seit Python 2.6 die Tupelkonstruktion hier beseitigt, aber das ist eine interne Optimierung, die für Sie nie relevant sein sollte.)

Aber jede Quelle einer Sequenz der richtigen Länge ist auf der rechten Seite gültig. In Ihrem target, direction = max(...) Beispiel wählt max ein Element aus einer Liste von 2-Element Tupeln (neighbor, direction). Der "Größte" (wie durch den Parameter Schlüssel = definiert) wird zurückgegeben und in Ziel und Richtung entpackt.

+0

Danke! Ich dachte zunächst nicht über 'max (...)' zurück, sondern nur einen einzigen Wert. – Loaf