Diese Zeile verstehen: list_of_tuples = [(x, y) für x, y, label in data_one]

8

Wie Sie bereits verstanden haben, bin ich ein Anfänger und versuche zu verstehen, worauf der "pythonische Weg" zum Schreiben dieser Funktion aufgebaut ist. Ich weiß, dass andere Threads eine teilweise Antwort darauf enthalten können, aber ich weiß nicht, wonach ich suchen soll, da ich nicht verstehe, was hier passiert.

Diese Zeile ist ein Code, den mein Freund mir geschickt hat, um meinen Code zu verbessern, nämlich:

%Vor%

Die "verbesserte" Version:

%Vor%

Ich frage mich:

  1. Was passiert hier?
  2. Ist es ein besserer oder schlechterer Weg? da es "Pythonic" ist, nehme ich an, dass es nicht wäre Arbeit mit anderen Sprachen und vielleicht ist es besser, sich an den allgemeineren Weg zu gewöhnen?
oba2311 06.07.2016, 16:29
quelle

5 Antworten

15
%Vor%

(x, y) ist ein tuple & lt; - verknüpftes Tutorial.

Dies ist eine Liste Verständnis

%Vor%

data_one ist ein iterable und ist für ein Listenverständnis notwendig. Unter den Deckeln sind sie Schleifen und müssen über etwas iterieren.

x, y, label in data_one sagt mir, dass ich diese drei Elemente von jedem Element, das vom data_one iterable geliefert wird, "entpacken" kann. Dies ist genau wie eine lokale Variable einer for-Schleife, sie ändert sich bei jeder Iteration.

Insgesamt sagt das:

Erstelle eine Liste von Tupeln, die wie (x, y) aussehen, wobei ich x, y, and label von jedem Gegenstand erhalte, der vom iterablen data_one geliefert wird. Setzen Sie jedes x und y in ein Tupel innerhalb einer Liste namens list_of_tuples . Ja, ich weiß, ich habe label "entpackt" und es nie benutzt, das ist mir egal.

    
piRSquared 06.07.2016, 16:50
quelle
8

Beide Wege sind richtig und funktionieren. Sie könnten den ersten Weg wahrscheinlich mit der Art und Weise in Beziehung setzen, in der Dinge in C und anderen Sprachen erledigt werden. Dies bedeutet, dass Sie im Grunde eine for-Schleife ausführen, um alle Werte zu durchlaufen und sie dann an Ihre Tupelliste anzuhängen.

Der zweite Weg ist mehr pythonisch, macht aber dasselbe. Wenn Sie sich [(x,y) for x, y, label in data_one] ansehen (dies ist ein Listenverständnis), werden Sie sehen, dass Sie auch eine for-Schleife für dieselben Daten ausführen, aber Ihr Ergebnis ist (x, y) und alle diese Ergebnisse bilden eine Liste. So erreicht es das Gleiche.

Der dritte Weg (als Antwort der Kommentare hinzugefügt) verwendet eine Slice-Methode.

Ich habe ein kleines ähnliches Beispiel vorbereitet:

%Vor%

Sie alle machen das gleiche und geben [(1, 2), (2, 3), (4, 5)] zurück, aber ihre Laufzeit ist anders. Deshalb ist ein Listenverständnis ein besserer Weg, dies zu tun.

Wenn ich die erste Methode load_data() starte, bekomme ich:

%Vor%

Wenn ich die zweite Methode load_data_2() starte, bekomme ich:

%Vor%

Wenn ich die dritte Methode load_data_3() starte, bekomme ich:

%Vor%

Der zweite Weg, Listenverständnis, ist schneller!

    
Xavier Merino 06.07.2016 16:47
quelle
5

Die "verbesserte" Version verwendet ein Listenverständnis . Das macht den Code deklarativ (was du willst) und nicht Imperativ (Beschreiben, wie Sie bekommen, was Sie wollen).

Die Vorteile der deklarativen Programmierung bestehen darin, dass die Implementierungsdetails größtenteils weggelassen werden und die zugrunde liegenden Klassen und Datenstrukturen die Operationen optimal ausführen können. Zum Beispiel könnte eine Optimierung, die der Python-Interpreter in Ihrem obigen Beispiel vornehmen könnte, darin bestehen, die korrekte Größe des Arrays list_of_tuples vorzubelegen, anstatt das Array während der append() -Operation kontinuierlich skalieren zu müssen.

Um Sie mit den Listenergänzungen zu beginnen, erkläre ich Ihnen, wie ich normalerweise damit anfange, sie zu schreiben. Für eine Liste L schreibe etwas wie folgt:

%Vor%

Für jedes Element in L wird eine Variable extrahiert (das Zentrum x ) und kann verwendet werden, um die Ausgabeliste zu bilden (das x auf der linken Seite). Der obige Ausdruck bewirkt effektiv nichts und output ist gleich wie L . Imperativ ist es ähnlich wie:

%Vor%

Von hier aus könnte man jedoch erkennen, dass jedes x tatsächlich ein Tupel ist, das mit entpackt werden kann Tupel-Zuweisung :

%Vor%

Dadurch wird eine neue Liste erstellt, die nur das Element x aus jedem Tupel in der Liste enthält.

Wenn Sie ein anderes Tupel in die Ausgabeliste packen wollten, packen Sie es einfach auf die linke Seite:

%Vor%

Das ist im Grunde, was Sie in Ihrer optimierten Version haben.

Sie können andere nützliche Dinge mit Listenüberlegungen tun, z. B. nur Werte einfügen, die einer bestimmten Bedingung entsprechen:

%Vor%

Hier ist ein nützliches Tutorial über Listenkompressen, die Sie vielleicht interessant finden: Ссылка

    
Lee Netherton 06.07.2016 17:05
quelle
4

Die Aktion ist im Wesentlichen die gleiche. In neueren Python-Interpretern ist der Umfang der Variablen im Listenverständnis enger ( x kann nicht außerhalb des Verständnisses gesehen werden).

%Vor%

Diese Art von Aktion tritt oft genug auf, so dass Python-Entwickler es für sinnvoll hielten, eine spezielle Syntax zu verwenden. Es gibt eine map(fn, iterable) -Funktion, die etwas Ähnliches macht, aber ich denke, das Listenverständnis ist klarer.

Python-Entwickler mögen diese Syntax genug, um sie auf Generatoren, Wörterbücher und Sets zu erweitern. Und sie erlauben Verschachtelung und bedingte Klauseln.

Beide Formulare verwenden das Tupel-Entpacken x,y,label in data_one .

Was machen diese beiden Clips? data_one ist anscheinend eine Liste von Tupeln (oder Unterlisten) mit 3 Elementen. Dieser Code erstellt eine neue Liste mit 2 Element-Tupeln - 2 der 3 Elemente. Ich denke, es ist einfacher, das im Listenverständnis zu sehen.

Es ist klug, mit beiden vertraut zu sein. Manchmal ist die Aktion zu kompliziert, um sie in die Verständnisform zu bringen.

Ein weiteres Merkmal des Verständnisses - es erlaubt keine Nebenwirkungen (oder es ist zumindest schwieriger, sie zu integrieren). Das mag in einigen Fällen ein Defekt sein, aber im Allgemeinen macht es den Code klarer.

    
hpaulj 06.07.2016 16:53
quelle
3

Dies wird als Listenverständnis bezeichnet. Es ist ähnlich wie eine Schleife und kann oft die gleiche Aufgabe ausführen, wird aber eine Liste mit den Ergebnissen erzeugen. Das allgemeine Format ist [operation for variable in iterable] . Zum Beispiel

[x**2 for x in range(4)] würde in [0, 1, 4, 9] resultieren.

Sie können auch komplizierter gemacht werden (wie oben), indem Sie mehrere Funktionen, Variablen und Iterables in einem Listenverständnis verwenden. Zum Beispiel

[(x,y) for x in range(5) for y in range(10)] .

Weitere Informationen zu diesem finden Sie hier .

    
Alex Rosenfeld 06.07.2016 16:41
quelle