Grundstruktur Listenbearbeitung#

Dieses Notebook: Ein einfaches, aber vollständiges kleines Programm. Zu besprechen in einer Frühphase des Erlernens von Python. Die Studierenden verstehen noch nicht alles, aber ein Dozent kann einiges daran erstmals exemplarisch zeigen. Zweck: Eine Idee geben, wie grundlegende Sprachelemente miteinander zusammenhängen.

Hinweis 2023-10-13: Viele der Beispiele lassen sich mit einer List Comprehension wesentlich eleganter formulieren. Aber eine List Comprehension versteht man nur, wenn man die Beispiele verstanden hat.

  • Also zunächst mal “zu Fuß” mit einer expliziten for-Schleife und manuellem Konstruieren der Ergebnis-Liste.

  • Später dann die Aufgabe “Stellen Sie die bereits gelöste Aufgabe mit einer List-Comprehension dar!”

Beispiel#

Gegeben: eine Liste von Klausurnoten.

  • z.B. [ 1, 2, 5, 3, 1]

Annahme: Studierende dürfen Fehlversuche streichen.

Gesucht: Eine Liste sowie der Notenschnitt von allen bestandenen Klausuren.

  • z.B. [ 1, 2, 3, 1], Schnitt: 1.75

# Eingabe
Liste_input = [ 1, 2, 5, 3, 1]

# Ausgabe
Liste_output = []
Summe = 0

# Objekt nimmt nacheinander jeden Wert aus der Eingabeliste an
for Objekt in Liste_input:
    
    # erfüllt das Objekt alle gewünschten Eigenschaften?
    if Objekt < 5:
        
        # Objekt an die Ausgabeliste anhängen
        Liste_output.append( Objekt )
        
        # Objekt zur Summe hinzuaddieren
        Summe += Objekt

Schnitt = Summe / len( Liste_output )

print("übernommene Noten:", Liste_output, "Schnitt:", Schnitt )
übernommene Noten: [1, 2, 3, 1] Schnitt: 1.75

AlsVorschau dasselbe mit einer List-Comprehension:

# List Comprehension
Liste_output = [ Objekt for Objekt in Liste_input if Objekt < 5 ]

Schnitt = sum( Liste_output ) / len( Liste_output )

# modernere Printsyntax mit f-String
print(f"übernommene Noten: {Liste_output} Schnitt: {Schnitt}" )
übernommene Noten: [1, 2, 3, 1] Schnitt: 1.75

Erweiterung: “gut” ist Note 2#

Die obige Grundstruktur lässt sich nun erweitern. So seien die Klausurnoten nicht nur durch Zahlen, sondern alternativ auch durch Text gegeben.

  • z.B. Liste_input = [ 1, 2, 5, "krank", "befriedigend", "im Ausland", "mit Auszeichnung"]

Lösungsansatz: Bilde Text über ein dict auf eine Note ab.

  • z.B. Note_aus_Text = {"sehr gut": 1, "mit Auszeichnung": 1, ...: ... }

Note_aus_Text = {"sehr gut": 1, "gut": 2,
                 "befriedigend": 3, "ausreichend": 4,
                 "mangelhaft": 5, "ungenügend": 6,
                 "mit Auszeichnung": 1,
                 "krank": None}

Liste_input = [ 1, 2, 5, "krank", "befriedigend", "im Ausland", "mit Auszeichnung"]

Liste_output = []
Summe = 0

for Objekt in Liste_input:
    
    # haben wir eine Zahl?
    if isinstance(Objekt, (float, int)):
        Note = Objekt
    
    # oder haben wir einen uns bekannten Text?
    elif Objekt in Note_aus_Text:
        Note = Note_aus_Text[Objekt]
    
    # nichts erkannt
    else:
        Note = None
        
    if Note != None and Note <= 4:
        Liste_output.append(Note)
        Summe += Note

Schnitt = Summe / len(Liste_output)

print("übernommene Noten:", Liste_output, "Schnitt:", Schnitt )
übernommene Noten: [1, 2, 3, 1] Schnitt: 1.75

Slicing#

minimale Einführung hier, quasi Vorausschau, nur um das Sprachelement zu zeigen. Ausführlicher z.B. https://note.nkmk.me/en/python-slice-usage/

l = [ 'a', 'b', 'c', 'd', 'e', 'f']
l[0:3]
['a', 'b', 'c']
l[0] # die Zählung beginnt mit 0
'a'
l[0:2] # wählt l[0] und l[1] aus, denn l[2] ist nicht mehr 'drinn'
['a', 'b']
l[0:5:2] # l[0] bis l[4] in Zweierschritten
['a', 'c', 'e']
[ 'a', 'b', 'c', 'd', 'e', 'f'][0:5:2] # ein Slice einer direkt angegebenen Liste
['a', 'c', 'e']

Insbeondere auch Strings sind sliceables:

s = "abcdef"
s[0:5:2]
'ace'

Lernerfolskontrolle: Erkläre die Syntax

[0,1,2][0:1:2]

Was kommt ‘raus?’

Verallgemeinerung#

Verallgemeinerung der Grundstruktur “durch eine Liste durchgehen”: Durchgehen kann man auch durch ein

  • dict

  • Generator

    • range()

    • Zufallszahlen

Durchgehen durch ein dict#

  • z.B. { "Januar": 31, "Februar": 28, "März": 31 }

In einem Dict haben wir zur Verfügung die Methoden

  • keys()

  • values()

  • items()

Beispiele:

# Tage im Monat
TiM = { "Januar": 31, "Februar": 28, "März": 31, "April": 30, "Mai": 31 }

for x in TiM:
    print(x)
Januar
Februar
März
April
Mai
for x in TiM.keys():
    print(x)
Januar
Februar
März
April
Mai
for x in TiM.values():
    print(x)
31
28
31
30
31

Interessant ist die Methode items(). Sie gibt zwei Werte zurück!

# x zeigt hier auf ein Zweitupel 
for x in TiM.items():
    print( x[0:2] )
('Januar', 31)
('Februar', 28)
('März', 31)
('April', 30)
('Mai', 31)
# hier werden die 2 Rückgabewerte von items() direkt den zwei Variablen zugewiesen
for ( p, q ) in TiM.items():
    print("p:", p, "q:", q)
p: Januar q: 31
p: Februar q: 28
p: März q: 31
p: April q: 30
p: Mai q: 31
# die Klammern kann man auch weglassen
for p, q in TiM.items():
    print("p:", p, "q:", q)
p: Januar q: 31
p: Februar q: 28
p: März q: 31
p: April q: 30
p: Mai q: 31

Durchgehen durch eine automatisch generierte Liste von Zahen: range()#

Erklärung zu range(): Googeln hilft, Erklärungen gibt es im Netz zuhauf. Hier nur ein Beispiel:

for i in range(1, 5):
    print(i)
    
1
2
3
4

Man bemerke: Die erste Zahl ist inkludiert, die zweite excludiert.

Liste von Zufallszahlen#

siehe Doku: https://docs.python.org/3/library/random.html

import random

# erzeuge 5 Zufallszahlen zwischen 2000 und 2024
for i in range(5):
    print(random.randrange(2000, 2024))
2011
2013
2002
2009
2018

Beispielaufgaben#

Beispielaufgaben unterschiedlicher Schwierigkeit, die aber alle mit dem Grundmuster plus ein paar einfache Operationen lösbar sind.

Häufigkeit von Elementen einer Liste#

Gegeben: Eine Liste z.B. von Buchstaben

Buchstabenliste = list("Hallo Welt!")
print(Buchstabenliste)
['H', 'a', 'l', 'l', 'o', ' ', 'W', 'e', 'l', 't', '!']
x = {"a": 7 }
x["a"] = 1000
x
{'a': 1000}
x["b"] = 2000
x
{'a': 1000, 'b': 2000}
# das erzeugt einen Fehler
# x["c"] += 1

# Recherche-Aufgabe: Statt den Fehler abzufangen 
# kann man einen Default-Wert angeben: Wie? 

gesucht: ein Dict, das für jeden Kleinbuchstaben die Häufigkeit angibt.

Haeufigkeit = {}

for b in Buchstabenliste:
    
    if b in "abcdefghijklmnopqrstuvwxyzöäüß":
        
        # Ist der key b neu für uns?
        # key neu anlegen und Zähler mit 1 initialisieren
        if b not in Haeufigkeit:
            Haeufigkeit[b] = 1
            
        # oder kennen wir den key schon?
        # Zähler um 1 erhöhen!
        else:
            Haeufigkeit[b] += 1
    
print(Haeufigkeit)
{'a': 1, 'l': 3, 'o': 1, 'e': 1, 't': 1}

Set aus Liste erzeugen#

Dafür gibt es eigentlich die Funktion set(). Aber wir kennen diese Funktion noch nicht, wir wollen sie programmieren.

Gegeben: Eine Liste L1 von Zahlen.

Gesucht: eine zweite Liste L2, in der jede Zahl aus L1 nur einmal vorkommt. Die Reihenfolge ist egal; insbesondere muss L2 nicht sortiert sein.

Tupel in einer Liste bearbeiten: Zeitabschnitte#

Gegeben:

  • eine Liste des Beginns und Ende wichtiger Zeitabschnitte. Bei Zeitabschnitten, die bis heute andauern, ist als Ende None angegeben.

    • z.B. K = [ (1939, 1945), (1955, 1975), (1979, 1989), (1980, 1988), (2003, 2011), (1991, 2001), (2011, 2011), (2014, None),  (2014, None), (1988, None), (2022, None), (2023, None) ]

Gesucht:

  • Eine Liste von Dreitupeln, bei denen zu jedem Zeitabschnitt auch die Dauer angegeben ist.

    • z.B. K_Dauer = [ (1939, 1945, 7),  ..., (2011, 2011, 1), (1988, None, None)  ]

  • Eine Menge des Anfangs der Zeitabschnitte, die bis heute andauern.

    • z.B. K_andauernd = { 2014, 1988, 2022 }