Notes 6
Sie können diese Seite ausdrucken oder mit einem PDF-Drucker in ein PDF umwandeln, um Ihre eigenen Notizen hinzuzufügen.
Willkommen!
- In den vergangenen Wochen haben Sie grundlegende Bausteine der Programmierung kennengelernt.
- Sie lernten die Low-Level-Programmiersprache C kennen.
- Heute werden wir mit einer höheren Programmiersprache namens Python arbeiten.
- Während Sie diese neue Sprache lernen, werden Sie feststellen, dass Sie besser in der Lage sind, sich selbst neue Programmiersprachen beizubringen.
Python
- Die Menschen haben im Laufe der Jahrzehnte erkannt, wie frühere Designentscheidungen verbessert werden können.
- Python ist eine Programmiersprache, die auf dem aufbaut, was Sie bereits in C gelernt haben.
- Anders als C ist Python eine interpretierte Sprache, bei der Sie Ihr Programm nicht separat kompilieren müssen. Stattdessen führen Sie Ihr Programm im Python Interpreter aus.
Hallo
-
Bis zu diesem Punkt sah der Code in etwa wie folgt aus:
// Ein Programm, das der Welt "Hallo" sagt #include <stdio.h> int main(void) { printf("Hallo, Welt"); }
-
Heute ist das Programmieren einfacher.
-
Zum Beispiel wird der obige Code in Python wie folgt dargestellt:
# Ein Programm, das der Welt Hallo sagt print("Hallo, Welt")
Beachten Sie, dass das Semikolon wegfällt und dass keine Bibliothek benötigt wird.
-
Python kann insbesondere das, was in C recht kompliziert war, relativ einfach umsetzen.
Filter
-
Um diese Einfachheit zu verdeutlichen, erstellen Sie eine neue Datei, indem Sie “code blur.py” in Ihr Terminalfenster eingeben, und schreiben Sie den folgenden Code:
# Verwischt ein Bild from PIL import Image, ImageFilter # Bild unscharf machen before = Image.open("bridge.bmp") after = before.filter(ImageFilter.BoxBlur(10)) after.save("out.bmp")
Beachten Sie, dass dieses Programm die Module
Image
undImageFilter
aus einer Bibliothek namensPIL
importiert. Es nimmt eine Eingabedatei und erstellt eine Ausgabedatei. -
Mit Python können Sie bei der Programmierung noch mehr von den Details abstrahieren als in C und anderen niedrigeren Programmiersprachen.
CS50-Bibliothek
-
Wie in C kann auch in Python eine cs50-Bibliothek verwendet werden, um den Einstieg zu erleichtern.
-
Die folgenden Funktionen sollten Ihnen bekannt vorkommen:
get_float get_int get_string
-
Anders als in C können Sie in Python nur die tatsächlich benötigten Funktionen aus der CS50-Bibliothek importieren:
from cs50 import get_float, get_int, get_string
Strings
-
In C erinnern Sie sich vielleicht an diesen Code:
// get_string und printf mit %s #include <cs50.h> #include <stdio.h> int main(void) { string answer = get_string("Wie ist Ihr Name?"); printf("Hallo, %s\n", answer); }
-
Dieser Code sieht in Python so aus:
# get_string und print, mit Format-Strings (f-Strings) from cs50 import get_string answer = get_string("Wie ist Ihr Name?") print(f"hallo, {answer}")
Beachten Sie, wie die geschweiften Klammern es der Funktion
print
ermöglichen, dassanswer
darin erscheint. Dasf
ist erforderlich, umanswer
im String richtig zu formatieren (sog. f-String). Das funktioniert nicht nur in print, sondern überall, wo Strings verwendet werden. -
Ohne CS50-Stützräder:
answer = input("Wie ist Ihr Name? ") print(f"hallo, {answer}")
Variablen
- Auch die Variablendeklaration wird vereinfacht. In C könnten Sie
int counter = 0;
angeben. In Python würde dieselbe Zeile lauten:counter = 0
. Sie müssen den Typ der Variablen nicht angeben, weil Python eine dynamisch typisierte Sprache ist (C ist statisch typisiert). - Python nutzt
counter += 1
, um um eins zu erhöhen. Die aus C bekannte Möglichkeit mitcounter++
gibt es in Python nicht.
Typen
-
Datentypen müssen in Python nicht explizit deklariert werden. Sie haben zum Beispiel oben gesehen, dass
Antwort
eine Zeichenkette ist, aber wir mussten dem Interpreter nicht sagen, dass dies der Fall ist: Er wusste es von selbst; den Datentyp hat er sich selbst erschlossen. -
In Python werden häufig folgende Typen verwendet:
bool float int str
Beachten Sie, dass
long
unddouble
fehlen. Python nutzt für größere Zahlen automatisch Repräsentationen mit ausreichender Genauigkeit. -
Sie können das selbst ausprobieren, indem Sie den Python-Interpreter in einem Terminal durch Eingabe von
python
(oderpython3
) im interaktiven Modus starten und folgendes eingeben:10**100
– das Ergebnis dieser Potenzierung von 10 mit der Zahl 100 ist eine Zahl mit 101 Stellen – und wäre in C nicht ohne weiteres in einer Variablen speicherbar. -
Einige andere Datentypen in Python sind:
range (Sequenz von Zahlen) list (Listen, deren Größe automatisch angepasst wird) tuple (Tupel, also nicht veränderbare Listen) dict (Dictionaries mit Key-Value-Paaren) set (Mengen ohne Duplikate)
-
Jeder dieser Datentypen kann auch in C implementiert werden, aber in Python können sie einfacher implementiert werden.
Rechner
-
Vielleicht erinnern Sie sich an
calculator.c
von früher im Kurs:// Addition mit int #include <cs50.h> #include <stdio.h> int main(void) { // Aufforderung an den Benutzer zur Eingabe von x int x = get_int("x: "); // Aufforderung an den Benutzer zur Eingabe von y int y = get_int("y: "); // Addition durchführen printf("%i\n", x + y); }
-
Wir können einen einfachen Taschenrechner genauso implementieren, wie wir es in C getan haben. Geben Sie
code calculator.py
in das Terminalfenster ein und schreiben Sie folgenden Code:# Addition mit int [mittels get_int] from cs50 import get_int # Benutzer zur Eingabe von x auffordern x = get_int("x: ") # Benutzer zur Eingabe von y auffordern y = get_int("y: ") # Addition durchführen print(x + y)
Beachten Sie, wie die CS50-Bibliothek importiert wird. Dann werden “x” und “y” vom Benutzer abgefragt. Schließlich wird das Ergebnis ausgegeben. Beachten Sie, dass die Funktion “main”, die in einem C-Programm zu sehen wäre, völlig fehlt! Obwohl man eine “main”-Funktion verwenden könnte, ist sie nicht erforderlich.
-
Wir versuchen auch hier wieder, die Stützräder der CS50-Bibliothek zu entfernen. Ändern Sie Ihren Code wie folgt:
# Addition mit int [mit input] # Benutzer zur Eingabe von x auffordern x = input("x: ") # Benutzer zur Eingabe von y auffordern y = input("y: ") # Addition durchführen print(x + y)
Beachten Sie, dass die Ausführung des obigen Codes zu einem sehr seltsamen Programmverhalten führt. Woran mag das liegen?
-
Wenn Sie an dieser Stelle vermutet haben, dass der Python-Interpreter
x
undy
als Strings betrachtet und daher die Konkatenation vonx
undy
ausgibt, dann liegen Sie damit richtig. Sie können den Code korrigieren, indem Sie die Funktionint
zur Typumwandlung wie folgt verwenden:# Addition mit int [mit Eingabe] # Benutzer zur Eingabe von x auffordern x = int(input("x: ")) # Benutzer zur Eingabe von y auffordern y = int(input("y: ")) # Addition durchführen print(x + y)
Beachten Sie, wie die Eingabe für
x
undy
an die Funktionint
übergeben wird, die sie in eine Ganzzahl umwandelt. Ohne die Umwandlung von “x” und “y” in Ganzzahlen werden die Zeichen aneinandergereiht (konkateniert).
Bedingte Anweisungen
-
Aus unseren C-Vorlesungen kommt Ihnen vielleicht ein Programm wie dieses vertraut vor
// Bedingte Anweisungen, boolesche Ausdrücke, relationale Operatoren #include <cs50.h> #include <stdio.h> int main(void) { // Aufforderung zur Eingabe von Ganzzahlen int x = get_int("Wie groß ist x? "); int y = get_int("Wie lautet y? "); // Ganzzahlen vergleichen if (x < y) { printf("x ist kleiner als y\n"); } else if (x > y) { printf("x ist größer als y\n"); } else { printf("x ist gleich y\n"); } }
-
In Python würde das wie folgt aussehen:
# Bedingte Anweisungen, boolesche Ausdrücke, relationale Operatoren from cs50 import get_int # Benutzer zur Eingabe von Ganzzahlen auffordern x = get_int("Wie groß ist x? ") y = get_int("Wie lautet y? ") # Ganzzahlen vergleichen if x < y: print("x ist kleiner als y") elif x > y: print("x ist größer als y") else: print("x ist gleich y")
Beachten Sie, dass es, erstens, keine geschweiften Klammern mehr gibt. Stattdessen werden Einrückungen verwendet. Zweitens wird ein Doppelpunkt in der “if”-Anweisung verwendet. Außerdem wird
else if
durchelif
ersetzt. Auch Klammern sind in den Anweisungenif
undelif
nicht mehr erforderlich. -
Anders als in C lassen sich Strings genauso einfach vergleichen:
# Benutzer zur Eingabe von Strings auffordern s = input("s? ") t = input("t? ") if s == t: print("same") else: print("different")
-
Betrachten Sie den bereits bekannten C-Code, um weitere Vergleiche anzustellen:
// Logische Operatoren #include <cs50.h> #include <stdio.h> int main(void) { // Aufforderung an den Benutzer, zuzustimmen char c = get_char("Sind Sie einverstanden?"); // Prüfen, ob einverstanden if (c == 'Y' || c == 'y') { printf("Einverstanden.\n"); } else if (c == 'N' || c == 'n') { printf("Nicht einverstanden.\n"); } }
-
Dies kann in Python wie folgt umgesetzt werden:
# Logische Operatoren from cs50 import get_string # Aufforderung an den Benutzer zuzustimmen s = get_string("Sind Sie einverstanden?") # Prüfen, ob einverstanden if s == "Y" or s == "y": print("Einverstanden.") elif s == "N" or s == "n": print("Nicht einverstanden.")
Beachten Sie, dass die beiden Senkrechtstriche, die in C verwendet werden, durch “or” ersetzt werden. In der Tat bevorzugen viele Menschen Python auch deswegen, weil es für Menschen besser lesbar ist. Beachten Sie auch, dass es in Python kein
char
gibt. Stattdessen wird auch für einzelne Zeichen der Datentyp “str” verwendet; die in C erforderliche Unterscheidung (einfache oder doppelte Anführungszeichen) gibt es hier nicht. -
Eine “pythonischere” (more pythonic) Herangehensweise an das Problem würde wie folgt aussehen. Hier wird der Datentyp Liste verwendet (Notation in eckigen Klammern):
# Logische Operatoren, die Listen verwenden from cs50 import get_string # Aufforderung an den Benutzer zuzustimmen s = get_string("Sind Sie einverstanden?") # Prüfen, ob einverstanden if s in ["y", "yes"]: print("Einverstanden.") elif s in ["n", "nein"]: print("Nicht einverstanden.")
Beachten Sie, dass wir mehrere Schlüsselwörter wie “y” und “ja” in einer “Liste” ausdrücken können.
-
Etwas unelegant ist, dass wir für alle Varianten von Groß- und Kleinschreibung nun entsprechende Elemente in den Listen benötigen. In C würden wir die Zeichen in
s
mit tolower(…) aus der Bibliothekctype.h
in Kleinbuchstaben umwandeln (Zeichen für Zeichen in einer Schleife).
Objektorientierte Programmierung
-
Unter Designgesichtspunkten ist das Anbieten einer Funktion wie tolower(…) nicht besonders elegant. Nach dem Include steht sie im Programm einfach so zur Verfügung wie jede andere Funktion. Bei vielen Includes wird es schnell unübersichtlich und es könnte sogar zu Namenskonflikten kommen, wenn z.B. mehrere Bibliotheken gleichzeitig included werden, die die gleichen Funktionen anbieten. Bisher haben wir das so hingenommen.
-
Wäre es nicht schöner, wenn die Funktionen, die bestimmte Daten verarbeiten, näher bei den Daten definiert wären, auf die sie anwendbar sind?
-
In der Realität sind wir es gewohnt, dass Objekte zum einen Eigenschaften mit sich bringen und zum anderen bestimmtes Verhalten haben. Ein Auto hat vier Räder und eine bestimmte Farbe. Es kann beschleunigen und bremsen.
-
Es bietet sich an, dieses Konzept auch bei der Programmierung zu verwenden und dadurch den Code besser zu organisieren.
-
Das ist die Idee der objektorientierten Programmierung, in der wir nicht mit unstrukturierten Daten arbeiten, sondern mit Objekten.
-
Mit C können wir das nicht umsetzen. Wir können lediglich eine struct erstellen, um mehrere Variablen innerhalb eines einzigen, selbst erstellten Datentyps miteinander zu verbinden. In Python können wir hingegen objektorientiert programmieren – und haben das von Anfang an getan, weil in Python alles ein Objekt ist!
-
Beim objektorientierten Programmieren können wir nicht nur mehrere Werte zu einem Objekt zusammenfassen, sondern auch Funktionen auf den Objekten aufrufen, die zu Objekten von einem bestimmten Typ (einer Klasse) gehören. Solche Funktionen nennen wir Methoden. Methoden werden durch den Punktoperator auf ein Objekt angewendet.
-
Zum Beispiel haben str-Objekte in Python eine eingebaute Methode, mit denen wir alle Großbuchstaben in Kleinbuchstaben umwandeln können Daher könnten Sie Ihren Code wie folgt ändern:
# Objektorientiertes Programmieren from cs50 import get_string # Aufforderung an den Benutzer zuzustimmen s = get_string("Sind Sie einverstanden?").lower() # Prüfen, ob zugestimmt wurde if s.lower() in ["y", "yes"]: print("Einverstanden.") elif s.lower() in ["n", "nein"]: print("Nicht einverstanden.")
Man beachte, wie dadurch anstelle des Werts von
s
das Ergebnis vons.lower()
, einer eingebauten Methode vonstr
, verwendet wird. -
Mehr über String-Methoden erfahren Sie in der Python-Dokumentation
-
Bitte schauen Sie sich die Short-Videos zum Objektorientierten Programmieren an. Dort zeigen wir nicht nur, wie man Objekte nutzt, die es schon gibt, sondern auch wie man selbst Klassen erstellt und Probleme objektorientiert modelliert.
Schleifen
-
while-Schleifen in Python funktionieren auf den ersten Blick recht ähnlich wie Schleifen in C. Sie erinnern sich vielleicht an den folgenden Code in C:
// Demonstriert die while-Schleife #include <stdio.h> int main(void) { int i = 0; while (i < 3) { printf("miau\n"); i++; } }
-
In Python sieht dieser Code wie folgt aus:
# Demonstriert die while-Schleife i = 0 while i < 3: print("miau") i += 1
-
Die for-Schleifen wird in Python hingegen anders implementiert:
# Besseres Design for i in range(3): print("miau")
Beachten Sie, dass
i
gar nicht benötigt wird. Python erhöht aber natürlich trotzdem in jedem Durchlauf (unnötigerweise) den Wert voni
. Wenn man ausdrücken will, dass man den Wert gar nicht benötigt, kann man einen Unterstrich_
statt desi
schreiben. Das macht den Code besser lesbar, weil es nicht zu Missverständnissen kommen kann (andernfalls könnte man sich irgendwann darüber wundern, dassi
nirgends verwendet wird) -
In ähnlicher Weise könnte man den obigen Code wie folgt ausdrücken:
# Abstraktion mit Parametrisierung # Miau eine bestimmte Anzahl von Malen def miau(n): for _ in range(n): print("miau") miau(3)
Beachten Sie, dass nun eine Funktion verwendet wird, um das Miauen auszulagern.
-
Um unser Verständnis von Schleifen und Iteration in Python zu vertiefen, erstellen wir eine neue Datei mit dem Namen
uppercase.py
, die sich an C-Code anlehnt, den wir früher schon einmal geschrieben haben:# Zeichenkette mit Großbuchstaben, ein Zeichen nach dem anderen before = input("Vorher: ") print("Nachher: ", end="") for c in before: print(c.upper(), end="") print()
Beachten Sie, wie der benannte Parameter
end=
verwendet wird, um einen Parameter an die Funktionprint
zu übergeben. Wir brauchen hier einen benannten Parameter, weil print(…) für mehr Komfort so konstruiert wurde, dass es alle Positions-basierten Parameter mit Leerzeichen getrennt ausgibt. Dadurch gibt es keinen natürlichen Ort, wo wir einen Parameter zur Veränderung des Verhaltens platzieren können – und eine separate Funktionprint_without_newline
wäre nicht besonders elegant. Mit benannten Parametern können wir einer Methode unabhängig von der Position Parameter übergeben, auf die in der Methode zugegriffen werden kann. Beiprint
können wir dadurch das Standardverhalten verändern. Es gibt dann keinen Zeilenumbruch aus. -
Bei der Lektüre der Dokumentation stellen wir fest, dass die
upper()
-Methode vonstr
immer die gesamte Zeichenkette verarbeitet und wir daher weniger Code benötigen:# Zeichenkette auf einmal großschreiben before = input("Vorher: ") after = before.upper() print(f"Nachher: {after}")
Beachten Sie, dass “upper” auf die gesamte Zeichenkette angewendet wird.
-
Oder noch kürzer
# Zeichenkette auf einmal großschreiben before = input("Vorher: ") print(f"Nachher: {before.upper()}")
Abstraktion mit Funktionen
-
Wie wir heute schon angedeutet haben, können wir unseren Code verbessern, indem wir Funktionen verwenden und die Implementierungsdetails in Funktionen abstrahieren. Ändern Sie Ihren zuvor erstellten
miau.py
Code wie folgt:# Abstraktion def main(): for i in range(3): miau() # Einmal miauen def miau(): print("miau") main()
Beachten Sie, dass die Funktion
miau
die Anweisungprint
abstrahiert. Beachten Sie auch, dass die Funktionmain
am Anfang der Datei definiert ist und am Ende der Datei aufgerufen wird. Dies ist eine gängiges Programmiermuster in Python. Funktionen können erst aufgerufen werden nachdem sie definiert wurden. Weil es das Konzept der Funktionsprototypen nicht gibt, rufen wir einfach main() ganz am Ende der Datei auf – zu diesem Zeitpunkt hat der Python-Interpreter die ganze Datei eingelesen und kennt alle Funktionen, die main() kann. -
Wie aus C bekannt können wir Variablen zwischen Funktionen übergeben:
# Abstraktion mit Parametrisierung def main(): miau(3) # Miau eine bestimmte Anzahl von Malen def miau(n): for i in range(n): print("miau") main()
Beachten Sie, dass
miau
jetzt eine Variablen
benötigt. In der Funktionmain
können Siemiau
aufrufen und ihm einen Wert wie3
übergeben. Dann verwendet “miau” den Wert von “n” in der “for”-Schleife. -
Wenn Sie den obigen Code lesen, werden Sie feststellen, dass Sie als C-Programmierer in der Lage sind, den obigen Code ganz leicht zu verstehen. Zwar sind einige Konventionen anders, aber die Bausteine, die Sie zuvor gelernt haben, sind für Sie in dieser neuen Programmiersprache nun schneller nachvollziehbar.
Keine Trunkierung bei Division und Fließkomma-Ungenauigkeit
-
Erinnern Sie sich, dass wir in C die Erfahrung gemacht haben, dass die Division einer ganzen Zahl durch eine andere zu einem ungenauen, trunkierten Ergebnis führen kann.
-
Schauen wir uns an, wie Python eine solche Division handhabt, indem wir den Code für
calculator.py
ändern:# Division mit ganzen Zahlen, Nachweis der fehlenden Trunkierung x = int(input("x: ")) y = int(input("y: ")) z = x / y print(z)
Beachten Sie, dass automatisch ein Fließkomma-Wert ausgegeben wird – in C wäre das Ergebnis der Division hingegen auf die nächste Ganzzahl abgerundet (trunkiert) worden. Wenn Sie sich mehr Ziffern nach
.333333
ausgeben lassen würden, würden Sie sehen, dass wir auch in Python mit Gleitkomma-Ungenauigkeit leben müssen. -
Wir können diese Ungenauigkeit aufdecken, indem wir unsere Codes leicht abändern:
# Fließkomma-Ungenauigkeit # Benutzer zur Eingabe von x auffordern x = int(input("x: ")) # Benutzer zur Eingabe von y auffordern y = int(input("y: ")) # x durch y dividieren z = x / y print(f"{z:.50f}")
Hier sehen Sie ein Beispiel für eine weiterführende Syntax von Format-Strings, die so ähnlich funktioniert wie bei
printf
in C. Wir geben die Zahl mit 50 Nachkommastellen aus. Dadurch sehen wir die Ungenauigkeit von Fließkommazahlen.
Exceptions
-
Sehen wir uns noch einmal folgenden Code an:
from cs50 import get_int def main(): # Benutzer zur Eingabe von x auffordern x = get_int("x: ") # Benutzer zur Eingabe von y auffordern y = get_int("y: ") # Addition durchführen print(x + y) main()
Wenn Sie bei diesem Programm statt einer Zahl einen String eingeben (z.B.
cat
), dann werden Sie erneut aufgefordert eine Zahl einzugeben. Die CS50-Bibliothek kümmert sich intern um die Fehlerbehandlung. Wie macht sie das? -
Das beobachtete Verhalten ist nicht das Standardverhalten von Python. Das sehen wir, wenn wir versuchen,
get_int
nachzubauen. -
Ändern Sie
calculator.py
wie folgt:# Implementiert get_int def get_int(prompt): return int(input(prompt)) def main(): # Benutzer zur Eingabe von x auffordern x = get_int("x: ") # Benutzer zur Eingabe von y auffordern y = get_int("y: ") # Addition durchführen print(x + y) main()
Beachten Sie, dass die Eingabe von falschen Daten zu einem Fehler führt (
ValueError
) und das Programm abgebrochen wird. -
In Python und anderen modernen Programmiersprachen gibt es ein leistungsfähiges Konstrukt zur Fehlerbehandlung, sogenannte Exceptions.
-
Die Idee ist folgende: Anstatt für alle möglichen Fehlerfälle explizit mit bedingten Anweisungen Prüfschritte einzubauen, „versuchen“ (engl. to try), wir den Code auszuführen und behandeln (man sagt: “fangen”, engl. to catch) dabei möglicherweise auftretende Ausnahmezustände. Dazu ändern wir unseren Code wie wie folgt:
# Implementiert get_int mit einer Schleife def get_int(prompt): while True: try: return int(input(prompt)) except ValueError: print("Not an integer") def main(): # Benutzer zur Eingabe von x auffordern x = get_int("x: ") # Benutzer zur Eingabe von y auffordern y = get_int("y: ") # Addition durchführen print(x + y) main()
Beachten Sie, dass der obige Code wiederholt versucht, den richtigen Datentyp abzurufen, und bei Bedarf zusätzliche Eingabeaufforderungen liefert. So ähnlich arbeitet auch
get_int
im cs50-Modul.
Listen
-
list
ist eine sehr häufig genutzte Datenstruktur in Python. -
Für die Verarbeitung von Listen gibt es in Python einige nützliche Funktionen – und Listen haben zusätzlich viele nützliche Methoden.
-
Betrachten Sie zum Beispiel den folgenden Code:
# Durchschnitt von drei Zahlen in einer Liste # Punkte scores = [72, 73, 33] # Durchschnitt ausgeben average = sum(scores) / len(scores) print(f"Durchschnitt: {average}")
Beachten Sie, dass Sie die eingebaute Funktion
sum
verwenden können, um den Durchschnitt zu berechnen. -
Man könnte sich fragen, wieso man
sum(scores)
schreibt und nichtscores.sum()
– gleichermaßen bei len(…). Das liegt unter anderem daran, dass Listen nicht die einzigen Objekte sind, für die man eine Summe berechnen oder die Anzahl ermitteln können will. Diese Operationen könnten auch bei Tupeln oder Mengen nützlich sein. Tatsächlich sind sie bei allen Objekten sinnvoll, die man zählen kann bzw. die mehrere aufsummierbare Werte haben. Anstatt solche Funktionen in allen Klassen, in denen es Sinn macht, neu zu definieren, gibt es sie daher in Python global. Klassen, die sich summieren oder zählen lassen wollen, müssen diese Eigenschaft dann durch vordefinierte Methoden (sog. Dunder-Methods von „Double-Underscore“) anbieten. Mehr dazu erfahren Sie im Short-Video zum Objektorientierten Programmieren und zu Vererbung und Duck Typing. -
Sie können die folgende Syntax verwenden, um Werte vom Benutzer zu erhalten:
# Durchschnitt von drei Zahlen mit Hilfe einer Liste und einer Schleife from cs50 import get_int # Spielstände abrufen scores = [] for i in range(3): score = get_int("Score: ") scores.append(score) # Alternative: scores + [score] # Durchschnitt ausgeben average = sum(scores) / len(scores) print(f"Durchschnitt: {average}")
Beachten Sie, dass dieser Code die eingebaute Methode
append
für Listen verwendet. -
Sie können mehr über Listen in der Python-Dokumentation erfahren.
-
Sie können auch mehr über
len
in der Python-Dokumentation erfahren. -
Schauen Sie sich das Short-Video zu Collections und zu Vererbung und Duck Typing an. Dadurch werden Sie besser verstehen, wie Listen funktionieren und wie man sie in Python geschickt verwendet, um Probleme zu lösen.
Suche und Wörterbücher
-
Wir haben uns in C auch angesehen, wie man in Datenstrukturen nach einem bestimmten Wert sucht.
-
Betrachten wir ein Programm namens “phonebook.py”:
# Implementiert lineare Suche nach Namen mittels Schleife # Eine Liste von Namen names = ["Carter", "David", "John"] # Nach dem Namen fragen name = input("Name: ") # Suche nach Namen for n in names: if name == n: print("Gefunden") break else: print("Nicht gefunden")
Beachten Sie, dass dies eine lineare Suche nach dem Namen implementiert. Das
else
bei einer for-Schleife ist eine Python-Besonderheit, die wie folgt funktioniert. Wird die Schleife mit break abgebrochen, wird der else-Zweig nicht ausgeführt. Wird die Schleife erfolglos bis zum Ende durchlaufen (es wurde kein break aufgerufen), wird der else-Zweig ausgeführt. Praktisch, oder? -
Die obige Vorgehensweise ist nah am C-Code. Wir können uns langsam angewöhnen, mit Listen zu arbeiten – und dadurch Python die mühsamen Arbeiten für uns erledigen lassen. Wir müssen nämlich nicht von Hand über eine Liste iterieren. In Python können wir die gleiche lineare Suche stattdessen wie folgt erreichen:
# Implementiert die lineare Suche nach Namen mit "in". # Eine Liste von Namen names = ["Carter", "David", "John"] # Nach dem Namen fragen name = input("Name: ") # Suche nach Name if name in names: print("Gefunden") else: print("Nicht gefunden")
Beachten Sie, wie “in” zur Umsetzung der linearen Suche verwendet wird.
-
Dieser Code ist zwar elegant, aber nicht effizient.
-
Sie erinnern sich vielleicht noch daran, dass ein Wörterbuch (Pythons Datentyp
dict
, der mit geschweiften Klammern definiert wird) eine Sammlung von Schlüssel- und _Wert-_Paaren ist und dass Wörterbücher mit Hash-Tabellen sehr effizient implementiert werden können (konstante Laufzeit für die Suche bei Wahl einer geeigneten Hash-Funktion). -
Ein Telefonbuch können Sie in Python wie folgt implementieren (in C hatten wir es so ähnlich mit einer
struct
umgesetzt):# Implementiert ein Telefonbuch als eine Liste von Wörterbüchern from cs50 import get_string # Eine Liste, die aus drei Dictionaries besteht people = [ {"name": "Carter", "num": "+1-617-495-1000"}, {"name": "David", "num": "+1-617-495-1000"}, {"name": "John", "num": "+1-949-468-2750"}, ] # Suche nach Name name = get_string("Name: ") # je Durchlauf bekommen wir in "person" das aktuelle dict for person in people: if person["name"] == name: print(f"Gefunden {person['num']}") break else: print("Nicht gefunden")
Beachten Sie, dass das Telefonbuch als Liste aus Wörterbüchern implementiert ist, wobei jedes Wörterbuch zwei Key-Value-Paar hat: je eines für “name” und eines für “num”.
-
Wenn es uns um einen effizienten Zugriff geht, ist dieser Code allerdings nicht besonders gut designed – wir müssen ja, wie zuvor, alle Einträge mit linearer Suche abwandern, d.h. wir profitieren fast gar nicht von der Suche mit konstanter Laufzeit, die uns die Hash-Tabelle bietet. Der schnelle Zugriff, der die Vorteile von
dict
ausnutzt, erfolgt ja lediglich beim Zugriff aufname
undnum
, aber eben nicht bei der Suche nach dem richtigen Eintrag. -
Für unser einfaches Telefonbuch benötigen wir streng genommen aber weder
name
nochnum
! Wir können diesen Code daher wie folgt vereinfachen:# Implementiert ein Telefonbuch mit dict from cs50 import get_string people = { "Fuhrmann": "+1-617-495-1000", "David": "+1-617-495-1000", "John": "+1-949-468-2750", } # Suche nach Name name = get_string("Name: ") if name in people: print(f"Nummer: {people[name]}") else: print("Nicht gefunden")
Beachten Sie, dass people nun ein dict ist und mit geschweiften Klammern definiert wird. Die Anweisung
if name in people
prüft, obname
als Key im Wörterbuchpeople
enthalten ist. Beachten Sie auch, dass wir in der Anweisungprint
mit dem Wert vonname
im People-Wörterbuch indexieren können. Sehr nützlich! -
Python gibt sein Bestes, um bei der Suche eine konstante Zeit zu erreichen, indem es seine eingebauten Suchfunktionen verwendet.
-
Sie können mehr über Wörterbücher in der Python-Dokumentation erfahren.
Kommandozeilen-Argumente
-
Diesen Abschnitt haben wir aus Zeitgründen nicht in der Präsenzvorlesung behandelt.
-
Wie bei C können Sie auch in Python Kommandozeilen-Argumente verwenden. Betrachten Sie den folgenden Code:
# Druckt ein Kommandozeilenargument von sys import argv if len(argv) == 2: print(f"hallo, {argv[1]}") else: print("hallo, Welt")
Beachten Sie, dass
argv[1]
unter Verwendung einer formatierten Zeichenkette gedruckt wird, erkennbar an demf
in derprint
-Anweisung. -
Sie können alle Argumente in
argv
wie folgt ausgeben:# Kommandozeilenargumente ausgeben, Indizierung in argv von sys import argv for i in range(len(argv)): print(argv[i])
Beachten Sie, dass der obige Code das Wort “python” (den Python-Interpreter selbst) nicht ausgibt. Das erste Argument ist der Name der Datei, die Sie ausführen.
-
Sie können Teile von Listen wegschneiden (engl. to slice). Betrachten Sie den folgenden Code:
# Kommandozeilenargumente drucken from sys import argv for arg in argv[1:]: print(arg)
Beachten Sie, dass die Ausführung dieses Codes dazu führt, dass der Name der Datei, die Sie ausführen, weggeschnitten wird. Es werden alle Argumente ab dem ersten (nullindiziert, also eigtl. ab dem zweiten) ausgegeben.
-
Sie können mehr über die
sys
-Bibliothek in der Python-Dokumentation erfahren.
Exit-Code
-
Diesen Abschnitt haben wir aus Zeitgründen nicht in der Präsenzvorlesung behandelt.
-
Die
sys
-Bibliothek hat auch eingebaute Methoden. Wir könnensys.exit(i)
verwenden, um das Programm mit einem bestimmten Exit-Code zu beenden:# Beendet mit explizitem Wert, importiert sys import sys if len(sys.argv) != 2: print("Fehlendes Kommandozeilenargument") sys.exit(1) print(f"hallo, {sys.argv[1]}") sys.exit(0)
Beachten Sie, dass die Punkt-Notation verwendet wird, um die eingebauten Funktionen von “sys” zu nutzen, da wir das ganze sys-Modul importieren.
Bibliotheken von Drittanbietern
-
Diesen Abschnitt haben wir aus Zeitgründen nicht in der Präsenzvorlesung behandelt.
-
Einer der Vorteile von Python ist seine riesige Benutzerbasis und die ebenso große Anzahl von Bibliotheken von Drittanbietern.
-
Beispiel:
pip install qrcode
.# Generates a QR code # https://github.com/lincolnloop/python-qrcode import os import qrcode # Generate QR code img = qrcode.make("https://youtu.be/xvFZjo5PgG0") # Save as file img.save("qr.png", "PNG")
Zusammenfassend
In dieser Vorlesung haben Sie gelernt, wie die Bausteine der Programmierung aus früheren Vorlesungen in Python genutzt werden können. Außerdem haben Sie gelernt, wie mit Pythons Syntax einfacher Code geschrieben werden kann und wie Sie gängige Python-Funktion nutzen können.
Vermutlich haben Sie in dieser Vorlesung einige der Konzepte auf Anhieb verstanden. Das liegt nicht nur daran, dass die Syntax von Python leichter zugänglich ist als die Syntax von C. Es liegt auch daran, dass die Fähigkeiten und das Wissen aus den letzten Wochen Ihnen den Einstieg in eine neue Programmiersprache erleichtern. Sie verfügen nun über eine solide Basis, mit der Sie sich selbst neue Programmiersprachen aneignen können!
Vielleicht können Sie jetzt erahnen, wie Sie durch die Herangehensweise, die wir in diesem Kurs verfolgen, eine neue Art des Lernens entdecken – neugierig zu sein (Was passiert eigentlich, wenn ich hier … eingebe?) und nachzuhaken, um den Dingen auf den Grund zu gehen (Wieso ist das eigentlich so?). Diese Art des Lernens wird Ihnen hoffentlich beim Erlernen weiterer Programmiersprachen - und vielleicht auch beim Lernen in anderen Bereichen - von Nutzen sein.
Konkret haben wir besprochen…
- Python
- Variablen
- Konditionale
- Schleifen
- Typen
- Objektorientiertes Programmieren
- Trunkierung und Fließkomma-Ungenauigkeit
- Ausnahmen
- Wörterbücher
- Befehlszeilenargumente
- Bibliotheken von Drittanbietern
Bis zum nächsten Mal!