Einführung
Algorithmus
Ein zentraler Begriff in der Programmierung ist "Algorithmus". Deswegen wollen wir uns zum Einstieg zwei Definitionen dieses Begriffes anschauen und deren Essenz herausziehen.
G. Büchel, Praktische Informatik
Für Büchel ist also entscheidend, dass sich um eine
- endliche Folge
- von Operationen
- die maschinell ausgeführt werden können
handelt. Somit scheidet eine Anleitung wie "nach Gefühl mit Salz bestreuen" aus, weil sie nicht maschinell ausgeführt werden kann – zumindest nicht, solange Maschinen kein Gefühl haben. Genauso wenig kann "bestimme die Summe bis ins Unendliche" ein Algorithmus sein, weil hier keine endliche Folge von Anweisungen vorliegt.
Eine andere Definition liefert Boles, der aber auch auf die Präzision und die Ausführbarkeit durch einen Computer abhebt.
Dietrich Boles
- Formulierung von Algorithmen
- Umgangssprachlich
- Programmiersprache
- Aktivitätsdiagramme
- Ausführung von Algorithmen durch einen Prozessor (Mensch / Computer) → Prozess (process)
Generell ist erst einmal nicht festgelegt in welcher Form ein Algorithmus formuliert werden muss. Man kann ihn in umgangssprachliche Worte fassen, als Computerprogramm in einer Programmiersprache schreiben oder grafisch als Aktivitätsdiagramm darstellen. Entscheidend ist, dass man die verschiedenen Formen ineinander überführen kann und bei der Formulierung in Umgangssprache keine Doppeldeutigkeiten vorkommen, die eine Maschine nicht auflösen könnte.
Bei der Formulierung in einer Programmiersprache kann man auf jeden davon ausgehen, dass der Algorithmus maschinell ausführbar ist. Bei den anderen Formen bleibt ein Restrisiko, dass die Darstellung nicht präzise genug ist oder Dinge enthält, die man nicht einfach in ein Programm umwandeln kann.
Addiere für eine vorgegebene natürliche Zahl n
die Zahlen von 1 bis n. Dies ist das Resultat.
n = int(input())
erg = 0
aktZahl = 1
while (aktZahl <= n):
erg = erg + aktZahl
aktZahl = aktZahl + 1
print(erg)
Diesen Algorithmus könnte man auch problemlos als mathematische Formel darstellen, weil er hinreichend einfach ist.
Eine direkte Darstellung als geschlossene mathematische Formel ist aber nur bei den wenigsten Algorithmen möglich, weil wir häufig Wiederholungen (Schleifen) und Auswahlen benötigen, um ein komplexeres Problem zu lösen.
Programmierung
Aus einem Algorithmus wird ein Programm, indem wir ihn programmieren. Dabei geht es nicht nur darum, das eigentliche Programm in den Computer zu tippen, sondern in einem ersten Schritt das Problem so zu fassen, dass man ein Lösungsverfahren (Algorithmus) dazu entwickeln kann. Erst im letzten Schritt erfolgt die Formulierung in einer Programmiersprache und die Ausführung auf dem Computer.
Gerade für Einsteiger in die Programmierung bietet es sich an, mehr Zeit in die Formulierung des Problems und die Bestimmung des Lösungsverfahrens zu stecken.
Programmierung: Weg von der Formulierung des Problems bis zum erfolgreichen Einsatz des ausführbaren Programms
- Formulierung des Problems
- Bestimmung des Lösungsverfahrens (Algorithmus)
- Programmierung des Algorithmus in einer Programmiersprache
XKCD
In diesem Kurs werden wir die Programmierung anhand der Programmiersprache Python lernen. Als Einstieg in das Thema bietet sich der folgende Comic von XKCD an.
Python löst also offensichtlich alle Probleme; es hilft sogar dabei, die Schwerkraft zu überwinden – man muss nur das richtige Modul (siehe unten) importieren.
Eigenschaften von Python
Was ist Python?
- Entwickelt seit 1991 von Guido van Rossum in den Niederlanden
- Erste Veröffentlichung 1994 ⇒ genauso alt wie Java
- Extrem populär für wissenschaftliche Anwendungen
Warum bietet sich Python als Programmiersprache für Einsteiger an? Gerade bei Menschen, die keine Informatiker sind (Ingenieure, Wissenschaftler etc.), ist Python ausgesprochen beliebt. Einer der Gründe ist, dass sich die Programme sehr schnell erstellen und testen lassen, weil man keinen Compiler benötigt, um sie auszuführen. Das Programm ist direkt nach dem Eintippen – oder sogar während der Eingabe – ausführbar. Python bietet eine relativ hohe Abstraktion und erlöst den Programmierer deshalb von einer ganzen Anzahl an Details, um die er sich in anderen Programmiersprachen kümmern müsste.
Natürlich kommen diese Vorteile nicht ohne Nachteile Nebenwirkung, so bietet sich Python nicht an, wenn man viel Kontrolle über die Details oder eine besonders hohe Performance benötigt. Außerdem ist die Sprache nicht typsicher, sodass bei größeren Programmen die Fehlersuche komplizierter werden kann als in einer typisierten Sprache, wie z. B. Java.
Vorteile von Python
- Einfach zu lernen
- Programme lassen sich schnell erstellen
- Intuitive Verwendung
- Vielseitig (↔ Matlab oder R)
Nachteile
- Weniger Kontrolle über Details (↔ C)
- Schlechtere Performance (↔ C)
- Nicht typsicher, Nutzer ist verantwortlich (↔ Java)
Was sind die zentralen Eigenschaften von Python?
- Skriptsprache (⇒ kein Compiler)
- multiparadigmatisch
- objektorientiert
- prozedural
- funktional
- Metaprogrammierung
- aspektorientierte Programmierung
- alles ist ein Objekt
- dynamische Typisierung
- plattformunabhängig
Viele der hier genannten Eigenschaften klingen für einen Nichtinformatiker komplex und unverständlich.
Mit Skriptsprache ist gemeint, dass man Python-Programme direkt ausführen kann, ohne sie erst compilieren zu müssen. Der Programmquelltext wird direkt vom Interpreter ausgeführt; man benötigt keinen Compiler.
Multiparadigmatisch bedeutet, dass die Sprache nicht einem einzigen Programmierparadigma folgt, sondern eine ganze Reihe von verschiedenen Programmierstilen unterstützt. So kann man sowohl prozedural, als auch objektorientiert programmieren.
Bezüglich der Datentypen ist Python deutlich konsequenter als Sprachen, wie z.b. Java: Es wird nicht zwischen primitiven Datentypen und Objekten unterschieden; alles ist ein Objekt, auch die einfachen Datentypen, wie z. B. Ganzzahlen.
Außerdem wird der Entwickler davon verschont, sich Gedanken über die Typen seiner Variablen zu machen. Die Typen werden automatisch bestimmt, was als dynamische Typisierung bezeichnet wird. Eine Variable kann zu verschiedenen Zeiten, Werte unterschiedlichen Typs aufnehmen.
a = "Hallo"
a = 3
In anderen Programmiersprachen muss man den Typ einer Variablen bei deren Deklaration festlegen, und kann ihn danach nicht mehr ändern. Man spricht hier von einer statischen Typisierung, weil zur Laufzeit keine Anpassungen der Typen möglich sind.
String a = "Hallo";
int b = 3;
Des weiteren ist Python plattformunabhängig: Ein Programm, das unter einem Betriebssystem programmiert wurde, kann auf jedem anderen Betriebssystemen ausgeführt werden, für das es einen Python-Interpreter gibt.
Ziele von Python
Guido van Rossum hat selbst einmal seine Ziele für Python formuliert.
- einfach
- so einfach zu lesen wie reines Englisch
- intuitiv
- gleichwertig mit den Konkurrenten bezüglich Mächtigkeit
- Open Source
- für tägliche Aufgaben geeignet sein
- kurze Entwicklungszeiten ermöglichen
Nach: van Rossum, Computer Programming for Everybody
Es ging ihm darum, eine Sprache zu entwickeln, die möglichst einfach ist, aber trotzdem für alle Aufgaben zu verwenden, für die auch die Konkurrenten von Python (Ruby, Perl, etc.) eingesetzt werden. Dabei wollte er die Syntax so gestalten, dass sich Python-Programme ähnlich wie englische Sätze lesen lassen.
Python ist Open Source, d. h. jeder kann sich den Quelltext der Programmiersprache herunterladen und ihn nach eigenen Bedürfnissen anpassen. Außerdem muss man für die Verwendung von Python kein Geld bezahlen, sondern erhält es kostenlos.
Interaktiver Modus
Für Experimente mit Python bietet sich der interaktive Modus an. In ihm kann man die Python-Befehle direkt eintippen und sieht sofort das Ergebnis. Eine Besonderheit des interaktiven Modus ist, dass die Ergebnisse der Eingaben – anders als im Skriptmodus – direkt ausgegeben werden.
- Programme direkt interaktiv ausprobieren
- REPL = Read Evaluate Print Loop
- Start mit dem Kommando
python3
~$ python3
Python 3.8.6 (default, Jan 27 2021, 15:42:20)
>>> print('Hello World')
Hello World
>>> 2**3
8
>>> exit()
~$
Im Skriptmodus müsste man print(2**3) schreiben, um das Ergebnis zu sehen. Im interaktiven Modus wird der Rückgabewert jedes Funktionsaufrufs und das Ergebnis jeden Ausdrucks direkt ausgegeben.
exit() ruft eine Python-Funktion auf (mehr dazu später), die den Interpreter beendet.
Wenn Sie in ältere Bücher oder Anleitungen zu Python schauen, werden Sie dort manchmal die Form print 2**3 anstatt print(2**3) finden. Die Form ohne Klammern ist veraltet und wird nur in Python, Version 2 unterstützt.
Aufgabe:
Lösung:
~$ python3
Python 3.8.6 (default, Jan 27 2021, 15:42:20)
>>> 2**64
18446744073709551616
Skriptmodus
Der interaktive Modus ist nur dazu geeignet kurze Schnipsel auszuprobieren oder als Ersatz für einen Taschenrechner benutzt zu werden. Er ist ungeeignet für ernsthafte Programme – allein schon deshalb, weil man das Programm jedes Mal neu eintippen müsste. Will man Python-Programme entwickeln, verwendet man den Skriptmodus. Hierbei wird das Python-Programm in einer Textdatei abgelegt, die dann vom Interpreter ausgeführt werden kann.
- Die Befehle werden in ein Skript geschrieben (z. B.
hello-world.py) - Skript wird mit
python3 SKRIPTNAMEausgeführt - Auf Unix kann das Skript direkt gestartet werden, wenn die erste Zeile
#!/usr/bin/python3ist (Shebang)
#!/usr/bin/python3
print("Hello World")
~$ python3 hello-world.py
Hello World
Mit welchem Programm Sie die Datei erstellen ist egal, solange die Software wirklich reine Textdateien erzeugt. Textverarbeitungsprogramme, wie Word, scheiden also aus. Üblicherweise verwendet man einen Editor, der speziell für das Schreiben von Programmen entwickelt wurde, z. B. Visual Studio Code.
Die Dateiendung .py ist eine Konvention, an die man sich halten sollte, weil viele Werkzeuge nach der Endung schauen.
Die magische Zeile #!/usr/bin/python3 hat folgenden Zweck: Unter Unix kann man ein Python-Skript direkt als ausführbar markieren (chmod a+x DATEINAME). Dazu muss die erste Zeile des Skripts den Pfad zum Python-Interpreter enthalten. Den speziellen Ausdruck #! bezeichnet man als Shebang). Er muss in der ersten Zeile des Skriptes stehen, um zu funktionieren. Hat man einen entsprechendes Shebang in der Skript-Datei untergebracht, kann man sie als ausführbar markieren und direkt aufrufen:
~$ chmod a+x hello-world.py
~$ ./hello-world.py
Hello World
Die Angabe des Interpreters entfällt. Das ./ ist nötig, da Linux aus Sicherheitsgründen keine Dateien im aktuellen Verzeichnis (.) ausführt, außer man weist es mit ./ explizit dazu an.
Aufgabe:
bob.py, das die Ausgabe "Hello Bob" macht und starten Sie das Skript auf der Kommandozeile. Versuchen Sie das Skript über einen Shebang direkt ausführbar zu machen. Lösung:
#!/usr/bin/python3
print("Hello Bob")
~$ chmod a+x bob.py
~$ ./bob.py
Hello Bob
Kommentare
Nicht immer ist ein Programm vollkommen selbsterklärend, insbesondere für Personen, die es nicht programmiert haben. Deswegen hat man die Möglichkeit, das Programm mit Kommentaren zu versehen. Diese werden vom Python-Interpreter ignoriert, dienen aber dem Menschen dazu das Programm besser zu verstehen.
Kommentare werden in Python durch das #-Zeichen begonnen und erstrecken sich immer bis zum Ende der Zeile. D. h. alles zwischen # und dem Zeilenende wird vom Interpreter einfach ignoriert.
Alles nach einem # ist ein Kommentar
# Ein Kommentar am Anfang der Zeile
print("Hello") # Ein Kommentar am Ende einer Zeile
# Ein mehrzeiliger
# Kommentar
Man kann Kommentare auch verwenden, um Programmteile für Tests oder während der Entwicklung kurzzeitig auszukommentieren. Im fertigen Programm sollten solche Teile aber nicht mehr enthalten sein, weil sie einen unfertigen und undurchdachten Eindruck erwecken und als schlechter Stil gelten.
Werte und Typen
Wenn man ein Programm abstrakt betrachtet, dann bekommt es Eingabe-Daten, verarbeitet diese und produziert Ausgabe-Daten. Dieses einfache Modell gilt für alle Arten von Programmen, von der Textverarbeitung bis hin zu Cyberpunk 2077.
Daten (egal ob Eingabe- oder Ausgabedaten) haben zwei Eigenschaften:
- Sie haben einen Wert
- Sie haben einen Typ
- Programme manipulieren Werte, z. B.
"Hello World!",42,6.023E23,True - Werte haben einen Typ
- Python kann man mit
type(WERT)nach dem Typ fragen
>>> type("Hello World!")
<class 'str'>
>>> type(42)
<class 'int'>
>>> type(6.023E23)
<class 'float'>
>>> type(True)
<class 'bool'>
Die Unterscheidung ist wichtig, weil der Typ bestimmt, welche Operationen auf den Daten möglich sind und der Wert das Ergebnis der Operationen. Sie kennen diese strikte Trennung aus der Physik, bei der Sie auch immer die Einheit und die Größe betrachten. Eine Kraft wird in Newton angegeben und eine Strecke in Metern. Zur Berechnung eines Drehmomentes dürfen Sie die beiden Größen multiplizieren und erhalten als Einheit Newtonmeter (Nm). Eine Addition von Kraft und Strecke ist unsinnig und kommt deswegen nicht vor. Auch hier bestimmt die Einheit die möglichen Operationen und die Größe das Ergebnis.
Betrachten wir die Operation Addition: Diese ist nur sinnvoll für Daten, deren Typ numerisch ist, also int und float im Beispiel oben. Eine Addition zweier Wahrheitswerte (True + False) ist sinnlos. Im Gegensatz ergibt die Operation logisches UND keinen Sinn bei Zahlen, wohl aber bei Wahrheitswerten.
Deswegen müssen wir beim Programmieren nicht nur die Werte betrachten, sondern auch die Typen. In den meisten Fällen denkt man beim Programmieren nicht so intensiv über die Typen nach, weil man die richtigen Operationen intuitiv durchführt. Der Python-Interpreter muss hier mehr aufpassen und die Typen prüfen, damit keine sinnlosen Operationen erfolgen. Deswegen kann man den Interpreter mit der type auch danach fragen, welchen Typ ein Wert hat.
Die Schreibweise type(...) ist aus der Mathematik entlehnt, bei der man Funktionen definieren \( f(x) = x^2 \) und dann anwenden kann (\( f(2) = 4 \)). Die Definition der Funktion type kennen wir nicht, sehen hier aber die Anwendung der Funktion.
Anweisung
Eine Anweisung (statement) ist die kleinste ausführbare Einheit eines Programms und sagt dem Computer was er tun soll
Beispiele
- Zuweisen eines Wertes:
a = 5 - Berechnung der Summe zweier Zahlen:
a = 5 + 6 - Ausgabe eines Textes:
print("Hallo") - …
In Python erstreckt sich eine Anweisung normalerweise auf genau eine Zeile. Das Zeilenende beendet auch die Anweisung. In der nächsten Zeile findet man dann die nächste Anweisung. Ausnahmsweise können sich Anweisungen über mehrere Zeilen erstrecken, dann gelten besondere Regeln, die hier erst einmal übersprungen werden. Andere Programmiersprachen, wie Java oder C, haben ein spezielles Zeichen (;), das die Anweisung eindeutig beendet. Bei diesen ist es egal, wie viele Anweisungen man in eine Zeile packt.
Ausdruck
Ein Ausdruck (expression) verknüpft Operanden mit Hilfe eines Operators
- Operand (operand) ist der Wert der verknüpft werden soll
- Operator (operator) legt die Art der Verknüpfung fest
(z. B. Addition mit+)
19 + 7
Um rechnen zu können, verwenden wir Ausdrücke. Mit ihnen können wir aus bekannten Werten neue Werte berechnen. Auch dieses Konzept ist bereits aus der Mathematik bekannt, so ist z. B. x + 8 ein Ausdruck, der aus einem beliebigen Wert x einen neuen Wert, der um 8 größer ist berechnet. Ein Ausdruck besteht aus Operatoren und Operanden. Die Operatoren werden auf die Operanden angewendet, um ein neues Ergebnis zu erhalten. Im Ausdruck x + 8 ist + der Operator und x und 8 sind die Operanden.
Ein Ausdruck besteht aus
- Operanden die Werte miteinander verknüpfen (im Beispiel
19und7) - Operatoren welche die Art der Verknüpfung festlegen (im Beispiel
+)
Auch hier stellt sich wieder die Frage, welchen Typ das Ergebnis der Operation hat. Bei vielen Operatoren hängt der Typ des Ergebnisses vom Typ der Operanden ab. So ist z. B. der Typ von 5 + 2 eine Ganzzahl, weil beide Operanden Ganzzahlen sind. Der Typ von 5 + 2.0 ist allerdings vom Typ float, weil ein Operant vom Typ float ist.
Ein Ausdruck ist nicht zwingend identisch mit einer Anweisung, weil eine Anweisung aus mehreren Ausdrücken bestehen kann. So besteht z. B. die Anweisung a = 4 + 5 aus zwei Ausdrücken: dem Ausdruck 4 + 5 und der Zuweisung a = ....
Ganzzahlen (Integer)
Einer der gängigsten Datentypen ist die ganze Zahl (Integer oder int). Python definiert eine ganze Reihe von Operatoren, die man auf ihnen anwenden kann.
- Ganzzahlen (Integer) stellen beliebig große, ganze Zahlen dar
- Operatoren
+,-: Addition und Subtraktion*: Multiplikation**: Potenzierung/: Division//: Ganzzahlige Division%: Modulo
Eine Besonderheit, die man aus der Mathematik wahrscheinlich nicht kennt, sind die drei unterschiedlichen Divisions-Operatoren. Man kann dem Interpreter bei der Division zweier Ganzzahlen sagen, welchen Wert man als Ergebnis haben möchte haben möchte:
- das Ergebnis als Fließkommazahl (
5 / 2→2.5) - das Ergebnis als Ganzzahl (
5 // 2→2) - den Divisionsrest (
5 % 2→1)
Die anderen Operatoren sind wie aus der Mathematik bekannt. Da man Computerprogramme üblicherweise nur mit den Buchstaben des amerikanischen Alphabets schreibt, verwendet man für die Operatoren andere Zeichen, als man diese im Mathebuch finden würde.
## Addition und Subtraktion
5 + 2 # -> 7
5 - 2 # -> 3
# Division
5 / 2 # -> 2.5
5 // 2 # -> 2
# Modulo
5 % 2 # -> 1
# Multiplikation
5 * 2 # -> 10
# Potenzierung
5 ** 2 # -> 25
Eine Besonderheit von Python ist, dass Ganzzahlen keine Beschränkung bezüglich ihrer Länge haben, d. h. sie können beliebig große positive oder negative Zahlen darstellen.
>>> 10**89
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Andere Sprachen, wie Java, C oder C++, können dies nicht. Hier müssen Sie auf spezielle Bibliotheken zurückgreifen, wenn Sie Zahlen größer als 264 verarbeiten wollen.
Fließkommazahlen (Float)
Der zweite Datentyp für Zahlen in Python sind die Fließkommazahlen. Mit ihnen lassen sich rationalen Zahlen darstellen und Berechnungen auf Ihnen durchführen. Eine Darstellung irrationaler Zahlen ist nicht möglich, weil die Anzahl der Nachkommastellen begrenzt ist. Allerdings kann man auch irrationale Zahlen so weit annähern, dass es für die allermeisten Berechnungen ausreichend ist.
- Fließkommazahlen (Float) stellen rationalen Zahlen dar
- Genauigkeit und Wertebereich sind beschränkt
- Werden als Binärbrücke gespeichert ⇒ Rundungsfehler
- Operationen
+,-: Addition und Subtraktion*,**: Multiplikation, Potenzierung/,//: Division, ganzzahlige Division
>>> 0.1 + 0.1 + 0.1
0.30000000000000004
Bei der Verwendung von Fließkommazahlen ist zu beachten, dass sie zum einen einen beschränkten Wertebereich haben, d. h. nicht beliebig große oder kleine Zahlen darstellen können. Zum anderen sind sie auch in der Genauigkeit beschränkt, können also nur eine bestimmte Anzahl von Nachkommastellen abbilden.
Da Fließkommazahlen im Computer in einer bestimmten binären Darstellung gespeichert werden, kann nicht jede rationale Zahl auch als Fließkommazahl dargestellt werden. Dies sieht man im obigen Beispiel: Obwohl 0.1 + 0.1 + 0.1 0.3 ergeben sollte, hat das Ergebnis einen Rundungsfehler. Dieser basiert auf der internen Speicherung im Computer und ist nicht zu vermeiden.
Für technische Berechnungen sind die sehr klein Rundungsfehler im allgemein unwichtig, in der Finanzmathematik können sie aber erheblich stören, weil sie sich aufschaukeln können, weswegen man dort auf Ganzzahlen zurückgreift und einfach statt Euro 1/1000 oder 1/10000 Euro verwaltet.
Variablen
Programme sollen möglichst universell funktionieren, d. h. mit beliebigen Eingabedaten benutzt werden können. Was nützt mir eine Umrechnung von kW in PS, wenn ich jedes Mal das Programm ändern muss, um einen anderen Wert einzugeben. Deswegen verwendet man anstatt fester Werte sogenannte Variablen. Diese können zu verschiedenen Zeiten verschiedene Werte annehmen, sodass man das Programm mit ganz unterschiedlichen Werten eingesetzt werden kann.
Variablen ordnen einem Wert einen Namen zu
nachricht = "Hallo, Welt!"
n = 42
k = 23
e = 2.71
print(nachricht) # -> "Hallo, Welt!"
print(n * k * e) # -> 2617.86
Es ist meist besser, eine Variable anstatt eines Wertes zu verwenden
- Code ist leichter zu korrigieren
- Namen sind leichter zu verstehen
Aus Sicht des Programmierers sind Variablen Platzhalter für Werte, die erst später (also nachdem das Programm fertiggestellt wurde) bestimmt werden. Mit Variablen kann man dann – wieder ähnlich zur Mathematik – mit den Platzhaltern anstatt mit den konkreten Werten arbeiten.
Die Syntax für die Verwendung von Variablen ist einfach: Wie in der Mathematik wird der Variabel mit = ein Wert zugewiesen (Zuweisung). Das Gleichheitszeichen heißt deswegen auch Zuweisungsoperator. Im Programm kann man dann anstelle der Werte die Variablen verwenden; zur Laufzeit werden die Variablen durch ihren konkreten Wert ersetzt.
a = 2
b = 4
print(a * b) # -> 8
b = 12
print(a * b) # -> 24
An dieser Stelle ein Wort der Vorsicht: Das Gleichheitszeichen (=) in der Mathematik und das Gleichheitszeichen (=) in der Programmierung haben eine unterschiedliche Bedeutung: In der Mathematik drückt = aus, dass die Variabel den Wert hat, in der Programmierung weist es der Variabel den Wert. Will man im Programm ausdrücken, dass eine Variable einen Wert hat, also sicherstellen, dass sie diesen Wert trägt, dann verwendet man das doppelte Gleichheitszeichen (==).
Im folgenden mathematischen Ausdruck, hat x von Anfang an den Wert 3, was wir durch elementare Umformungen zeigen
In einem Programm weist man der Variable einen Wert zu, um diese Variable dann zu verwenden. Das = ist also keine Prüfung eines Wertes, sondern eine Zuweisung. Das folgende Programm zeigt dies.
# Wir weisen x einen Wert zu
x = 4
# Wir prüfen, ob die Gleichung erfüllt ist
print(3*x == 9)
False
Ein weiterer wichtiger Unterschied zur Mathematik besteht darin, dass Variablen ihren Wert beliebig oft ändern können. Eine Variable kann also mehr als einmal zugewiesen werden. Dies ist in der Mathematik nicht möglich. Das Konstrukt i = i + 1 wäre in einer mathematischen Formel nicht zulässig. Hier müsste man für jede Veränderung eine neue Variable einführen.
Referenz vs. Kopie
Eine kleine Komplexität versteckt sich noch hinter den Variablen: Abhängig von der Art der Variable wird sie unterschiedlich gespeichert. Bei den einfachen Datentypen in (int, float, …) enthält die Variable direkt den zu speichernden Wert. Bei komplexeren Datentypen (Referenzdatentypen) ist die Variabel nur eine Referenz auf den Wert. Referenz bedeutet, dass die Variable die Speicherstelle des eigentlichen Wertes enthält und man somit nur indirekt darauf zugreift.
Dieser Unterschied könnte einem eigentlich egal sein, er zeigt sich aber, wenn man z. B. zwei Variablen für einen Wert hat. Bei den einfachen Datentypen, handelt es sich dann um eine wirkliche Kopie, bei den Referenzdatentypen verweisen beide Variablen auf dasselbe Datenobjekt. Dies wird dann sichtbar, wenn man die Daten über eine Variable verändert.
- Bei einfachen Datentypen (
int,float, …) wird der Wert der Variable bei einer Zuweisung kopiert - Bei komplexen Typen (Liste, Sequenzen, Dictionaries, …) ist die Variable nur eine Referenz auf das Objekt
a = 2
b = a
b = b + 2
print(a) # 2
print(b) # 4
l = [1, 2]
k = l
k.append(3)
print(l) # [1, 2, 3]
print(k) # [1, 2, 3]
Das Beispiel zeigt das beschriebene Verhalten deutlich. Im ersten Fall wird b durch die Zuweisung b = a eine Kopie des Wertes (2) aus a zugewiesen. Änderungen an b haben keine Auswirkungen auf a. Im zweiten Fall, sind l und k nur Referenzen, die auf eine einzige Liste mit dem Inhalt [1, 2] zeigen. Verändere ich die Liste über k, so ist sie auch bei einem Zugriff über l verändert.
Schlüsselwörter
Welche Namen darf ich für Variablen verwenden? Um diese Frage zu beantworten, müssen wir uns zuerst überlegen welchen Namen wir nicht verwenden dürfen. Jede Programmiersprache definiert einen Satz sogenannter Schlüsselwörter. Das sind Wörter, die für die Programmiersprache reserviert sind und nicht als Variablennamen verwendet werden dürfen.
Python hat relativ wenige Schlüsselwörter verglichen mit anderen Programmiersprachen.
Schlüsselwörter sind reserviert und dürfen nicht als Variablennamen verwendet werden
False def if raise
None del import return
True elif in try
and else is while
as except lambda with
assert finally nonlocal yield
break for not
class from or
continue global pass
Jedes Schlüsselwort hat in Python eine besondere Bedeutung, so zeigt z. B. if an, dass eine Fallunterscheidung vorgenommen werden soll oder return, dass eine Funktion beendet wird. Die einzelnen Schlüsselwörter werden wir im folgenden noch behandeln.
Vergleichsoperatoren
Algorithmen Leben davon, dass man Fallunterscheidung treffen kann, wie das genau geht, sehen wir im Kapitel zu den Kontrollstrukturen. Deswegen bietet Python eine Reihe von sogenannten Vergleichsoperatoren an, mit denen ich Werte miteinander vergleichen kann. Das Ergebnis eines Vergleichs ist immer eine Wahrheitswert (True oder False), der anzeigt, ob der Vergleich erfolgreich war oder nicht.
Vergleichsoperatoren vergleichen zwei Werte und geben True (wahr) oder False (falsch) zurück
==: Gleich!=: Ungleich>: Größer<: Kleiner>=: Größer-gleich<=: Kleiner-gleich
Warum für den Test auf Gleichheit das doppelte Gleichheitszeichen (==) benutzt wird und nicht das einfache (=) wurde bereits bei den Variablen erläutert: Wir haben das einfache schon für die Zuweisung "verbraucht" und brauchen deswegen für den Vergleich ein anderes Zeichen.
5 == 2 # -> False
3 == 3 # -> True
5 != 4 # -> True
3 != 3 # -> False
5 < 3 # -> False
5 > 3 # -> False
3 > 3 # -> False
3 >= 3 # -> True
Logische Operatoren
Die Vergleichsoperatoren liefern mir für jeden Vergleich einen Wahrheitswert. Wenn ich mehrere Wahrheitswerte miteinander verknüpfen möchte, muss ich zu den logischen Operatoren greifen. Diese bekommen einen oder zwei Wahrheitswert(e) und bilden daraus einen neuen Wahrheitswert.
Logische Operatoren (logical operators) verknüpfen Wahrheitswerte (True, False) miteinander
and: logisches UNDor: logisches ODERnot: logisches NICHT
True and False # -> False
True and True # -> True
True or False # -> True
False or False # -> False
not True # -> False
not False # -> True
Vergleichsoperatoren und logische können verknüpft werden
# Ich
lieblingsfilm = "Avengers: Endgame"
geld = 12 # Euro
# Kino
film = "Avengers: Endgame"
eintritt = 13 # Euro
# Eisdiele
preis_spaghetti_eis = 6 # Euro
# Kann ich ins Kino?
(film == lieblingsfilm) and (eintritt <= geld) # -> False
# Kann ich Eis essen?
preis_spaghetti_eis <= geld # -> True
Lesen von der Console
Nicht immer will man alle Werte fest im Programm hinterlegt haben, sondern man möchte sie von außen bekommen. Die einfachste Möglichkeit hierzu ist es, die Daten von der Konsole einzulesen.
- Die Funktion
input(prompt)erlaubt es, Eingaben von der Konsole zu Lesen - Man kann die Eingabe mit
intundfloatin entsprechende Zahlen umwandeln
name = input("Wie heisst du?: ")
print("Hallo {}".format(name))
Wie heisst Du?: Thomas
Hallo Thomas
Bei input handelt es sich um eine Funktion, die einen Wert zurückgibt. Diese Rückgabe ist dann genau die Eingabe des Benutzers. Man kann den Rückgabewert einer Variablen zuweisen und weiter verwenden.
In print wird die seltsame Konstruktion "Hallo {}".format(name) benutzt. Sie leistet folgendes: Alle Platzhalter {} in der Zeichenkette (String) werden durch die Variablen ersetzt, die in Klammern beim .format() angegeben sind. Die Details zu dieser Syntax können wir jetzt noch nicht erläutern, deswegen sollten Sie das vorläufig einfach so hinnehmen und benutzen. Details zu Strings – einem weiteren Datentyp – folgen später.
Das folgende Beispiel zeigt, wie der Datentyp der Eingabe angepasst werden kann, indem man int(...) benutzt.
name = input("Wie heisst Du?: ")
alter = int(input("Wie alt bist du?: "))
print("Hallo {}, du bist {} Jahre alt".format(name, alter))