Show pageOld revisionsBacklinksBack to top This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ~~NOTOC~~ ====== Listen ====== <WRAP round todo> Teste das Programm <code python> schuelerliste = ["Anna", "Berta", "Charly", "Daniel", "Emil", "Ida", "Berta"] print(schuelerliste[0]) print(schuelerliste[4]) print(schuelerliste) # len steht fuer length print(len(schuelerliste)) </code> </WRAP> <WRAP round info> Der Ausdruck ''["Anna", "Berta", "Charly", "Daniel", "Emil", "Ida", "Berta"]'' im obigen Programm erzeugt eine sogenannte //Liste//. Abstrakt ist eine Liste eine Datenstruktur, die eine geordnete endliche Folge von Elementen enthält. Wie im Beispiel können Elemente mehrfach vorkommen. Der Wert der Variablen ''schuelerliste'' ist diese Liste. </WRAP> ===== Schleifen über Listen ===== <WRAP round todo> Der folgende Code illustriert, wie man eine Schleife programmiert, deren Laufvariable nacheinander die Elemente der Liste als Wert annimmt: <code python> schuelerliste = ["Anna", "Berta", "Charly", "Daniel", "Emil", "Ida", "Berta"] for s in schuelerliste: print(s) </code> </WRAP> <WRAP round info> Hier noch zwei Alternativen, die dasselbe wie der obige Code bewirken, aber etwas weniger elegant sind: * Mit einer ''for''-Schleife: <code python> schuelerliste = ["Anna", "Berta", "Charly", "Daniel", "Emil", "Ida", "Berta"] for zaehler in range(len(schuelerliste)): print(schuelerliste[zaehler]) </code> * Mit einer ''while''-Schleife; diese führe ich hier durch die Hintertür ein: So lange die Bedingung zwischen dem Schlüsselwort ''while'' und dem Doppelpunkt wahr ist, wird der eingerückte Code-Block wieder und wieder ausgeführt): <code python> schuelerliste = ["Anna", "Berta", "Charly", "Daniel", "Emil", "Ida", "Berta"] zaehler = 0 while zaehler < len(schuelerliste): print(schuelerliste[zaehler]) zaehler = zaehler + 1 </code> </WRAP> <WRAP round todo> Ergänze die Liste um weitere fünf Namen und modifiziere mindestens eines der obigen Programm so, dass nur jeder zweite Name aus der Liste ausgegeben wird! Wenn du magst, kannst du bei jedem Namen zusätzlich seine (gerade) Nummer in der Liste ausgeben. </WRAP> ===== Extraktion von Teil-Listen ===== <WRAP round todo> Der folgende Code illustriert, wie man Teillisten einer Liste bekommt. Versuche, die Syntax zu verstehen! Sie ist ähnlich wie beim ''range''-Befehl. <code python> schuelerliste = ["Anna", "Berta", "Charly", "Daniel", "Emil", "Ida", "Berta"] a = schuelerliste[1:4] print(a) b = schuelerliste[:4] # Lässt man den ersten Parameter weg, wird dieser also automatisch auf ... gesetzt. print(b) c = schuelerliste[2:] # Lässt man den zweiten Parameter weg, wird dieser automatisch auf ... gesetzt. print(c) d = schuelerliste[:] # Lässt man beide Parameter weg, so werden diese automatisch auf ... und ... gesetzt. # Dies ist nützlich, um eine Kopie der Liste zu erstellen, vgl. die Diskussion unten, wo wir erklären, dass Listen //mutabel// sind. print(d) # Die beiden Parameter dürfen auch negativ sein! Was bewirkt das? Hinweis: Zähle vom Ende der Liste! e = schuelerliste[-4:-1] print(e) # Auch ein dritter Parameter ist erlaubt (als Schrittweite). f = schuelerliste[0:5:2] print(f) </code> Expertenwissen: Sogar negative Schrittweiten sind erlaubt. <code python> g = schuelerliste[6:2:-1] print(g) </code> Um die Reihenfolge der Elemente einer Liste umzukehren, ist die folgende Syntax erlaubt. <code python> h = schuelerliste[::-1] # Beachte hier, dass die weggelassenen beiden ersten Parameter hier nicht wie oben durch ... und ... ersetzt werden, # sondern auf Grund der negativen Schrittweite durch ... und ... print(h) </code> </WRAP> <WRAP round todo> Oben hast du ein Programm geschrieben, dass nur jeden zweiten Namen aus einer Liste ausgibt. Das geht mit dem neuen Wissen deutlich kürzer! Wie? </WRAP> ===== Modifikation von Listen ===== <WRAP round todo> Der folgende Code illustriert, wie man eine Liste modifizieren kann! Versuche herauszubekommen, was jeder Befehl bewirkt! <code python> schuelerliste = ["Anna", "Berta", "Charly", "Daniel", "Emil", "Ida", "Berta"] schuelerliste[2] = "Carl" print(schuelerliste) schuelerliste.append("Friedrich") print(schuelerliste) schuelerliste.append("Marie") print(schuelerliste) name = schuelerliste.pop(3) print(name) print(schuelerliste) name = schuelerliste.pop() print(name) print(schuelerliste) schuelerliste.insert(2, "Gustav") print(schuelerliste) x = schuelerliste.index("Carl") print(x) print(schuelerliste) schuelerliste.remove("Carl") print(schuelerliste) schuelerliste.sort() print(schuelerliste) schuelerliste.reverse() print(schuelerliste) </code> Beachte die neue Syntax: (Name der Liste) + Punkt + Funktionsaufruf! Solche Funktionsaufrufe verändern bisweilen nur die Liste (wie ''insert'') bisweilen verändern sie die Liste und liefern einen Rückgabewert (wie ''pop''). </WRAP> <WRAP round todo> Schreibe ein Programm, welches den Benutzer nach Zahlen fragt und diese in einer Liste speichert. Wenn der Benutzer anstelle einer Zahl den Buchstaben ''q'' eingibt, soll die gesamte Liste ausgegeben werden und das Programm soll enden. Hinweis: Verwende eine ''while''-Schleife. Verwende den Befehl ''input'' statt ''inputString'' oder ''inputInt'', damit sowohl Zahlen als auch Buchstaben als Eingabe akzeptiert werden. </WRAP> ===== Was Listen alles enthalten können ===== <WRAP round info> Listen sind sehr flexible Datenstrukturen: Sie können als Elemente verschiedene Datentypen (Integers/ganze Zahlen; Strings/Zeichenketten; Boolesche Werte/Wahrheitswerte etc.) enthalten; Elemente können sogar selbst Listen sein: <code python> seltsameliste = ["Anna", 2, "Charly", True, [1, 2, False, "Hallo"]] print(seltsameliste) print(seltsameliste[4]) print(seltsameliste[4][2]) </code> </WRAP> ===== Listen erzeugen ===== <WRAP round todo> Verstehe die folgenden Befehle! <code python> zahlen = list(range(10)) print(zahlen) zahlen2 = list(range(10, 30, 3)) print(zahlen2) zahlen3 = [x*x for x in zahlen] print(zahlen3) </code> </WRAP> <WRAP round todo> Schreibe ein Programm, das mit Hilfe des [[https://de.wikipedia.org/wiki/Sieb_des_Eratosthenes|Siebs des Eratosthenes]] eine Liste aller Primzahlen bis zu einer gegebenen Grenze ''n'' ausgibt. </WRAP> ===== Listen sind mutabel/veränderlich (englisch mutable) ===== <WRAP round important> Welche Ausgabe erwartest du? <code python> a = [0, 1, 2, 3] b = a print(a) print(b) b[3] = 4 print(a) print(b) a.append(7) print(a) print(b) </code> Vermutlich überrascht dich die Ausgabe. Wir erklären das im Folgenden. </WRAP> <WRAP round info> Man sollte sich dies so vorstellen: In der ersten Zeile des obigen Programms wird die Liste [0, 1, 2, 3] irgendwo im Speicher angelegt, an einer gewissen //Speicheradresse// (das ist eine gewisse Position im Speichermedium, so wie eine Adresse eine gewisse Position auf der Welt kodiert). Beispielsweise könnte sie an der Speicheradresse 6 stehen: {{:lehrkraefte:snr:informatik:python:variable-als-verweis.jpg?direct&400|}} Die Variable ''a'' wird mit dem Befehl ''a = [0, 1, 2, 3]'' mit dieser Speicheradresse verknüpft (//verknüpfen// bedeutet, dass der Computer in einer Art Tabelle zu jedem Variablennamen die zugehörige Speicheradresse kennt). Hilfreich ist es, sich diese Verknüpfung wie im obigen Bild als Pfeil auf die entsprechende Position im Speicher vorzustellen. Man sagt deswegen auch, dass ''a'' auf diese Speicheradresse verweist. Der //Wert// von ''a'' ist das an dieser Speicheradresse gespeicherte Datum [0, 1, 2, 3]. Das obige Bild malt man kurz wie folgt: <WRAP round box> <nowiki> a ---------> [0, 1, 2, 3] </nowiki> </WRAP> Der Befehl ''b = a'' bewirkt, dass ''b'' auf dieselbe Speicheradresse verweist. <WRAP round box> <nowiki> a ---------> [0, 1, 2, 3] <--------- b </nowiki> </WRAP> Der Befehl ''b[3] = 4'' bewirkt das folgende: In der Liste, die sich an der zu ''b'' gehörenden Speicheradresse befindet, wird das Element mit Index 3 auf den neuen Wert 4 gesetzt. Die Speicheradresse der Liste bleibt dabei aber unverändert: Sowohl ''a'' als auch von ''b'' verweisen weiterhin auf diese Speicheradresse. <WRAP round box> <nowiki> a ---------> [0, 1, 2, 4] <--------- b </nowiki> </WRAP> Analoges gilt, wenn wir mit dem Befehl ''a.append(7)'' etwas an die Liste anhängen, die sich unter der zu ''a'' gehörenden Speicheradresse befindet. <WRAP round box> <nowiki> a ---------> [0, 1, 2, 4, 7] <--------- b </nowiki> </WRAP> Dass das bisher Gesagte stimmt, kann man mit Hilfe der Funktion ''id'' (für //Identität// oder //identity//) testen, die im Wesentlichen die Speicheradresse einer Variablen liefert: Beispielsweise ist ''id(a)'' die Speicheradresse von ''a''. <code python> a = [0, 1, 2, 3] b = a print(a) print(id(a)) print(b) print(id(b)) b[3] = 4 print(a) print(id(a)) print(b) print(id(b)) a.append(7) print(a) print(id(a)) print(b) print(id(b)) </code> In diesem Sinne sind Listen //mutable// (was man deutsch als //veränderlich// oder per Fremdwort als //mutabel// bezeichnen mag): Verweist eine Variable, etwa ''a'', auf eine solche Liste, so kann man diese Liste mit Befehlen wie ''a[3] = ...'' oder ''a.append(...)'' oder ''a.pop(...)'' verändern. Im Gegensatz dazu sind Integers, Floats, Strings, Booleans //immutable// (also //unveränderlich// oder //immutabel//): (Veränderungsbefehle wie bei Listen gibt es nicht.) <code python> a = 3 b = a b = 4 print(a) print(id(a)) print(b) print(id(b)) </code> Der Befehl ''b = a'' bewirkt wieder, dass ''a'' und ''b'' auf dieselbe Speicheradresse verweisen: <WRAP round box> <nowiki> a ---------> 3 <--------- b </nowiki> </WRAP> Da ''a'' als Integer-Variable immutabel ist, kann der Befehl ''b = 4'' den Inhalt der entsprechenden Speicheradresse nicht verändern. Stattdessen wird an einer freien Speicheradresse 4 als Wert der Variablen ''b'' gespeichert. Wovon hängt es ab, ob ein //Datentyp// (Beispiele für Datentypen sind strings, integers, floats, Booleans, lists) mutabel oder immutabel ist? Dies ist schlicht von den Entwicklern der Sprache Python so festgesetzt worden. Will man wirklich eine Kopie einer gegebenen Liste (an einer neuen Speicheradresse) erzeugen, so tut es((Bei verschachtelten Listen muss man besser aufpassen und die Befehle copy oder deepcopy aus dem Modul copy verwenden: Die unterschiedlichen Effekte sind hier illustriert: <code python> import copy a = [1, 2, ['x', 'y']] b = a c = a[:] d = copy.copy(a) # Meines Wissens besteht zwischen den Objekten a[:] und copy.copy(a) kein Unterschied. e = copy.deepcopy(a) a.append('z') a[2].append(3) print(a) print(b) print(c) print(d) print(e) print(id(a)) print(id(b)) print(id(c)) print(id(d)) print(id(e)) </code>)) der Befehl ''b = a[:]'': <code python> a = [0, 1, 2, 3] b = a[:] b[3] = 4 print(a) print(id(a)) print(b) print(id(b)) a.append(7) print(a) print(id(a)) print(b) print(id(b)) </code> Wer mehr wissen will, mag [[lehrkraefte:snr:informatik:python:variablen-in-python|hier]] weiterlesen. </WRAP> 2aLM und 2dNP bis hier am 27.10.2021 (jedenfalls einige) ===== Aufgaben ===== <WRAP round todo> <code python> n = 4 s = "Hallo" zahlen = list(range(1, n)) </code> Ergänze diesen Programmanfang so, dass eine Liste erzeugt und ausgegeben wird, deren Elemente wiederum Listen sind. Der i-te Eintrag dieser Liste soll aus der Liste ''zahlen'' entstehen, indem man dort vor der i-ten Position den String ''s'' als Element einfügt (im Fall i=n soll der String ''s'' am Ende angefügt werden). Die Ausgabe soll also wie folgt aussehen (sie soll sich aber natürlich ändern, wenn man ''n'' oder ''s'' ändert): <code text> [['Hallo', 1, 2, 3], [1, 'Hallo', 2, 3], [1, 2, 'Hallo', 3], [1, 2, 3, 'Hallo']] </code> </WRAP> <WRAP round todo> Schreibe ein Programm, das alle Permutation einer vorgegebenen Liste berechnet. Die Permutationen der Liste [1,2,3,4] sind beispielsweise wie folgt gegeben: <WRAP round box> [1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2], [1, 4, 2, 3], [1, 4, 3, 2], [2, 1, 3, 4], [2, 1, 4, 3], [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1], [3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [3, 2, 4, 1], [3, 4, 1, 2], [3, 4, 2, 1], [4, 1, 2, 3], [4, 1, 3, 2], [4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1] </WRAP> Bemerkung: Dies ist vermutlich recht schwierig. Eine mögliche Lösung ist <hidden hier> <code python> zuPermutierendeElemente = range(1, 5) ausgabeParameter = 6 permutationen = [[]] for x in zuPermutierendeElemente: neuepermutationen = [] for p in permutationen: for i in range(len(p) + 1): q = p[:] q.insert(i, x) neuepermutationen.append(q) permutationen = neuepermutationen[:] permutationen.sort() # Dieser Befehl sortiert die Liste. Er kann auch weggelassen werden. print(permutationen) print('') # Die Liste aller Permutationen in einer Zeile auszugeben war mir zu unübersichtlich... for i in range(len(permutationen) // ausgabeParameter): ausschnitt = permutationen[ausgabeParameter * i: ausgabeParameter * i + ausgabeParameter] print(', '.join(map(str, ausschnitt))) # Dies ist relativ kompliziert - bitte nachfragen! </code></hidden> angegeben - diese zu verstehen (Lernen am Beispiel) ist ebenfalls eine sehr lohnende Übung! </WRAP> ===== Wer hat Lust auf mehr? ===== * Auf der Seite [[lehrkraefte:blc:informatik:glf20:programmieren:listen|Listen]] von Herrn Blöchliger sind weitere Aufgaben und Erklärungen und Lösungsvorschläge. <WRAP round todo> (Gemeinsam besprechen?) Schreibe ein Programm, das eine vorgegebene Liste von Zahlen (oder Zeichenketten) sortiert OHNE die Listensortierfunktion sort() zu verwenden. Hinweis: Wie sortierst du einen Stapel von Karten? Bringe dein Verfahren dem Computer bei! (Es gibt ziemlich viele Verfahren!) </WRAP> <WRAP round todo> Das bekannte [[https://de.wikipedia.org/wiki/Magisches_Quadrat#Das_magische_Quadrat_von_Albrecht_D%C3%BCrer||magische Quadrat von Albrecht Dürer]] wird im folgenden Code-Teil als doppelt verschachtelte Liste gespeichert und auf zwei mehr oder weniger lesbare Arten ausgegeben. <code python> q = [[16,3,2,13],\ [5,10,11,8],\ [9,6,7,12],\ [4, 15, 14, 1]] print(q) print("") for zeile in q: print(zeile) </code> Ergänze diesen Code so, dass die Summen der Einträge aller Zeilen und aller Spalten berechnet werden (was dann zeigt, dass es sich wirklich um ein magisches Quadrat handelt). Schön formatiert könnte die Aussage etwa so aussehen: <code text> 16 3 2 13 | 34 5 10 11 8 | 34 9 6 7 12 | 34 4 15 14 1 | 34 -----------------+ 34 34 34 34 </code> </WRAP> <WRAP round todo> Challenge (für die Herbstferien?): Schreibe ein Programm, dass alle 880 magischen 4x4-Quadrate berechnet. </WRAP> ===== Link zur Kursseite ===== [[lehrkraefte:snr:informatik:glf21|Zur Kursseite]] lehrkraefte/snr/informatik/python/listen.txt Last modified: 2022/09/27 11:48by Olaf Schnürer