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. ====== Listen ====== ===== 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]] ~~NOTOC~~ ====== Bereits bekannte Sachverhalte zu Listen und Strings ====== <WRAP center round info> === Extraktion von Teillisten === * Extraktion von Teillisten mit ''<Name der Liste>[<Startindex>:<Endindex>]'', wobei die Teilliste beim Startindex beginnt und eine Position vor dem Endindex endet, z. B.: * ''meineListe[1:4]'' liefert die Liste ''["Berta", "Caesar", "Dora"]'' * als Indizes sind ähnlich wie im vorigen Punkt auch negative Zahlen erlaubt: Die Befehle ''meineListe[1:-3]'' oder ''meineListe[-6:4]'' oder ''meineListe[-6:-3]'' liefern ebenso die Liste ''["Berta", "Caesar", "Dora"]''. * Bei der Extraktion von Teillisten dürfen Start- oder Endindex weggelassen werden. * Lässt man den Startindex weg, so wird er "per default" minimal sinnvoll (also auf ''0'') gesetzt. Beispielsweise liefert ''meineListe[:4]'' die Liste ''["Anton", "Berta", "Caesar", "Dora"]''. Dieselbe Liste erhält man mit ''meineListe[:-3]'' * Lässt man den Endindex weg, so wird er "per default" maximal sinnvoll (also auf die Länge der Liste) gesetzt. Beispielsweise liefern ''meineListe[4:]'' und ''meineListe[-3:]'' die Liste ''["Emil", "Friedrich", "Gustav"]''. Ausserdem sei bekannt, dass der Befehl ''meineListe[::-1]'' die umgekehrte Liste ''["Gustav", "Friedrich", "Emil", "Dora", "Caesar", "Berta", "Anton"]'' liefert.((Für diejenigen, die es genau wissen möchten oder sich vage erinnern: Mit Hilfe der Syntax ''<Name der Liste>[<Startindex>:<Endindex>:<Schrittweite>]'' kann man eine Schrittweite als zusätzlichen dritten Parameter übergeben: * ''meineListe[1:5:2]'' liefert die Liste ''["Berta", "Dora"]''. * ACHTUNG: Hierbei sind auch negative Schrittweiten erlaubt: ''meineListe[5:1:-1]'' liefert die Liste ''["Friedrich", "Emil", "Dora", "Caesar"]''. * Lässt man bei positiver Schrittweite Start- bzw. Endindex weg, so wird dieser (ähnlich wie oben) minimal bzw. maximal gesetzt: * ''meineListe[::2]'' liefert dasselbe wie ''meineListe[0:7:2]'', nämlich die aus jedem zweiten Element bestehende Teilliste, also ''["Anton", "Caesar", "Emil", "Gustav"]''. * ACHTUNG: Lässt man bei negativer Schrittweite Start- bzw. Endindex weg, so wird dieser maximal bzw. minimal (was hier ''-1'' bedeutet) gesetzt. Dies erklärt, dass ''meineListe[::-1]'' die umgekehrte Liste liefert. )) === Zu Strings alias Zeichenketten === * Bezeichnet ''s'' einen String in Python, so liefert ''s.lower()'' denjenigen String, in dem alle Großbuchstaben von ''s'' durch Kleinbuchstaben ersetzt wurden. * Beispiel: Für ''s = "Goethes Faust, Teil I"'' liefert ''s.lower()'' den String ''"goethes faust, teil i"''. * Ähnlich wie oben bei Listen kann man auf die einzelnen Zeichen eines Strings bzw. einen Teil des Strings zugreifen. * Für ''s'' wie oben liefert * ''s[8]'' das Zeichen (alias den String der Länge Eins) ''"F"'', * ''s[8:13]'' den String ''"Faust"'', * ''s[-6:]'' den String ''"Teil I"'', * ''s[::-1]'' den String ''"I lieT ,tsuaF sehteoG"''. * Die Funktion ''len'' liefert die Länge eines Strings, z. B. liefert ''len(s)'' im obigen Beispiel die Zahl ''21''. </WRAP> === Retour zur Hauptseite === [[lehrkraefte:snr:informatik:fachdidaktik:list-comprehension|Fortgeschrittene Techniken für Listen samt Aufgaben zu Goethes Faust]] ====== Ideen ====== for-loop über Liste * Strings? length, Substrings mit [::] (alles dann wieder bei Listen); replace, find, uppercase, split, Befehl ''dir'' erklären. Dann "Drei Chinesen ..." ersetze. Uppercase. * "Brauche" Listen: String-Befehle, rauskriegen etwa per ''dir(s)'' wobei ''s'' String ist lehrkraefte/snr/informatik/glf22/python/listen-altes-material.txt Last modified: 2022/09/26 20:44by Olaf Schnürer