lehrkraefte:snr:informatik:python:listen

Listen

Teste das Programm

schuelerliste = ["Anna", "Berta", "Charly", "Daniel", "Emil", "Ida", "Berta"]
print(schuelerliste[0])
print(schuelerliste[4])
print(schuelerliste)
 
# len steht fuer length
print(len(schuelerliste))

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.

Der folgende Code illustriert, wie man eine Schleife programmiert, deren Laufvariable nacheinander die Elemente der Liste als Wert annimmt:

schuelerliste = ["Anna", "Berta", "Charly", "Daniel", "Emil", "Ida", "Berta"]
for s in schuelerliste:
    print(s)

Hier noch zwei Alternativen, die dasselbe wie der obige Code bewirken, aber etwas weniger elegant sind:

  • Mit einer for-Schleife:
    schuelerliste = ["Anna", "Berta", "Charly", "Daniel", "Emil", "Ida", "Berta"]
    for zaehler in range(len(schuelerliste)):
        print(schuelerliste[zaehler])
  • 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):
    schuelerliste = ["Anna", "Berta", "Charly", "Daniel", "Emil", "Ida", "Berta"]
    zaehler = 0 
    while zaehler < len(schuelerliste):
        print(schuelerliste[zaehler])
        zaehler = zaehler + 1

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.

Der folgende Code illustriert, wie man Teillisten einer Liste bekommt. Versuche, die Syntax zu verstehen! Sie ist ähnlich wie beim range-Befehl.

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)

Expertenwissen: Sogar negative Schrittweiten sind erlaubt.

g = schuelerliste[6:2:-1]
print(g)

Um die Reihenfolge der Elemente einer Liste umzukehren, ist die folgende Syntax erlaubt.

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)

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?

Der folgende Code illustriert, wie man eine Liste modifizieren kann! Versuche herauszubekommen, was jeder Befehl bewirkt!

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)

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).

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.

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:

seltsameliste = ["Anna", 2, "Charly", True, [1, 2, False, "Hallo"]]
print(seltsameliste)
print(seltsameliste[4])
print(seltsameliste[4][2])

Verstehe die folgenden Befehle!

zahlen = list(range(10))
print(zahlen)
zahlen2 = list(range(10, 30, 3))
print(zahlen2)
 
zahlen3 = [x*x for x in zahlen]
print(zahlen3)

Schreibe ein Programm, das mit Hilfe des Siebs des Eratosthenes eine Liste aller Primzahlen bis zu einer gegebenen Grenze n ausgibt.

Welche Ausgabe erwartest du?

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)

Vermutlich überrascht dich die Ausgabe. Wir erklären das im Folgenden.

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:

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:

a ---------> [0, 1, 2, 3]

Der Befehl b = a bewirkt, dass b auf dieselbe Speicheradresse verweist.

a ---------> [0, 1, 2, 3] <--------- b

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.

a ---------> [0, 1, 2, 4] <--------- b

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.

a ---------> [0, 1, 2, 4, 7] <--------- b

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.

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))

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.)

a = 3
b = a
b = 4
print(a)
print(id(a))
print(b)
print(id(b))

Der Befehl b = a bewirkt wieder, dass a und b auf dieselbe Speicheradresse verweisen:

a ---------> 3 <--------- b

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 es1) der Befehl b = a[:]:

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))

Wer mehr wissen will, mag hier weiterlesen.

2aLM und 2dNP bis hier am 27.10.2021 (jedenfalls einige)

n = 4
s = "Hallo"
zahlen = list(range(1, n))

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):

[['Hallo', 1, 2, 3], [1, 'Hallo', 2, 3], [1, 2, 'Hallo', 3], [1, 2, 3, 'Hallo']]

Schreibe ein Programm, das alle Permutation einer vorgegebenen Liste berechnet. Die Permutationen der Liste [1,2,3,4] sind beispielsweise wie folgt gegeben:

[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]

Bemerkung: Dies ist vermutlich recht schwierig. Eine mögliche Lösung ist

hier

hier

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!

angegeben - diese zu verstehen (Lernen am Beispiel) ist ebenfalls eine sehr lohnende Übung!

  • Auf der Seite Listen von Herrn Blöchliger sind weitere Aufgaben und Erklärungen und Lösungsvorschläge.

(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!)

Das bekannte |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.

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)

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:

  16   3   2  13 |   34
   5  10  11   8 |   34
   9   6   7  12 |   34
   4  15  14   1 |   34
-----------------+
  34  34  34  34

Challenge (für die Herbstferien?): Schreibe ein Programm, dass alle 880 magischen 4×4-Quadrate berechnet.


1)
Bei verschachtelten Listen muss man besser aufpassen und die Befehle copy oder deepcopy aus dem Modul copy verwenden: Die unterschiedlichen Effekte sind hier illustriert:
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))
  • lehrkraefte/snr/informatik/python/listen.txt
  • Last modified: 2022/09/27 11:48
  • by Olaf Schnürer