Einführung in Python
Inhalt
Einführung in Python¶
Online-Resourcen
Es gibt im Internet eine Vielzahl an guten Einführungen zum Thema Programmieren in Python.
Hier zwei Beispiele:
Insbesondere zu als Anfänger ist die Menge an Tutorials überwältigend und es fällt schwer zu beurteilen, was davon geeignet und für unsere Zwecke sinnvoll ist. Je mehr Erfahrung und Übung Sie jedoch bekommen, desto einfacher fällt es zielgerichtet im Internet nach Hilfe zu suchen.
Natürlich gibt es auch eine Vielzahl an guten Büchern zum Thema Programmieren und Python. Eine ganz besonders gelungene Einführung in das Thema Programmieren mit Python bietet Zelle [Zel16]. (siehe hier). Das Buch empfiehlt sich insbesondere für diejenigen von Ihnen, die die Grundlagen des Programmierens nicht nur aus Datenanalyse-Perspektive betrachten wollen.
Einfache Arithmetik¶
Beginnen wir mit einfachen mathematischen Operationen. Das Beispiel zeigt einen Ausdruck bzw. Statement (im Folgenden verwenden wir den Begriff Statement
) mit Berechnungen. Dieser Ausdruck ist in Python geschrieben:
1 + (5 * 12) / 3 - 12
69.44444444444444
Wie man sieht, kann man - analog zu einem Taschenrechner (oder Excel) - die bekannten arithmetischen Operatoren verwenden.
+
= Addition
-
= Subtraktion
*
= Multiplikation
/
= Division
**
= Potenzieren (❗ die Schreibweise für \(3^4\) in Python lautet \(3{**}4\))
Dieses Vorgehen ist jedoch meist nicht sinnvoll und wenig vorteilhaft gegenüber z.B. einem Taschenrechner. Auch in einem typischen Tabellenkalkulationsprogramm wie Excel würden wir anders vorgehen, da wird dort typischerweise nicht eine komplette Formel mit fest codierten Werten in eine Zelle schreiben, da dies umständlich, wenig flexibel und fehleranfällig wäre. Gleiches gilt für Python.
In Excel würden wir stattdessen die Werte auf verschiedene Zellen aufteilen und in einer Ergebniszelle verknüpfen. Dieses Vorgehen hat den Vorteil, dass die Annahmen für das Ergebnis viel transparenter und Änderungen in Annahmen auf einen Blick ersichtlich sind. So wird z.B. deutlich, dass es sich bei der \(12\), die in der Berechnung zwei Mal vorkommt (Zellen C5 und C7) um tatsächlich zwei verschiedene Annahmen handelt - sonst würden wir nicht zwei Inputparameter benötigen -, die nur zufällig den selben Wert haben.
Zuweisen von Variablen¶
Das Äquivalen in Python ist die Nutzung von Variablen. Wir können Werte als Variablen abspeichern1, in dem wir das “=
”-Symbol benutzen.
Wir schreiben also
<variable> = <wert>
variable
kann hier jeden Namen annehmen2. Für wert
können wir Ganzahlen, Dezimalzahlen, Wörter oder auch ganz andere sog. Datentypen - z.B. Listen, Graphen oder Dataframes die wir jeweils noch kennenlernen werden - einsetzen.
Hier ein paar Beispiele:
zahl = 42
wort = "Spaghetti"
satz = "Deutscher Meister wird nur der BVB"
Namen für Variablen sollten sinnvoll und prägnant (d.h. nicht zu lang) sein. In Python gibt es darüber hinaus die Konvention (siehe PEP 8), dass Variablen klein geschrieben werden und mehrere Wörter mit “_
” getrennt werden.
Beispiel:
sehr_wichtige_variabel = 321
Diese Konvention ist für die Funktion eines Programms nicht entscheiden, jedoch erleichtert diese die Lesbarkeit des Codes.
Wir können unser obiges Formelbeispiel also verbessern, in dem wir die Annahmen in verschiedene Variablen speichern und dann miteinander zu einem Ergebnis kombinieren.
input1 = 1
input2 = 5
input3 = 12
input4 = 3
input5 = 12
ergebnis = input1 + (input2 * input3) / input4 - input5
ergebnis
9.0
Beispiel: Berechnung Kapitalbarwert
Lassen Sie uns unser neugewonnenes Wissen direkt mithilfe eines konkreten Anwendungsfalles ausprobieren. Wir wollen berechnen, ob sich eine Investition lohnt. Hierfür haben wir untenstehende Annahmen gegeben:
Investition (\(I_0\)): -10.000
Cashflows (\(CF_t\)) in den Jahren 1 bis 3: 5.000, 4.000 und 3.000
Zinssatz (\(i\)): 4%
Wir suchen den Kapitalbarwert (\(KW_0\)) der Investition und können diesen mit dem untenstehendem Code berechnen
I_0 = -10000
CF_1 = 5000
CF_2 = 4000
CF_3 = 3000
i = 0.04
KW = I_0 + CF_1/(1+i)**1 + CF_2/(1+i)**2 + CF_3/(1+i)**3
KW
1172.9062357760577
Die Umsetzung war einfach und hat viele Vorteile gegenüber einer Variante, in der wir keine Variablen nutzen. Jedoch hat der bis hierhin vorgestellte Ansatz immer noch relativ viele Nachteile.
Zum einen ist der Code sehr repetitive, d.h. wir müssen bspw. für jeden Cashflow eine eigene Variable definieren und addieren auch jeden Cashflow separat auf. Dies ist nicht nur ein relativ großer manueller Aufwand, sondern auch fehleranfällig.
Zum anderen muss die Formel für den Kapitalbarwert für jede unterschiedliche Anzahl an Cashflows angepasst werden. Hat ein Projekt bspw. zwei oder sechs verschiedene Cashflows, dann müsste die Formel angepasst werden.
Repetitiver Code
Als generelle Daumenregel können wir bereits an dieser Stelle darauf hinweisen, dass wir repetitiven Code generell vermeiden und wir diesen optimieren sollten.
Im Folgenden wollen wir versuchen unseren Code zu verbessern bzw. zu optimieren. Wir werden Schritt für Schritt neue Konstrukte einführen. Der Code wird so weniger repetitv und flexibler einsetzbar. Die hier eingeführten Konstrukte sind unabhängig vom gewählten Beispiel und generisch einsetzbar.
Wichtige Regeln in Python¶
An dieser Stelle macht es Sinn einige grundsätzliche Regeln von Python zu erläutern.
Kommentare: Statements, denen ein “#
” vorangestellt wird, werden von Python nicht als Code erkannt. Wir können so Kommentare im Code einfügen.
# Dies ist ein Statement, um einer Variable einen Wert zuzuweisen
var = 3
Einrücken zu Beginn eines Statments: im Gegensatz nahezu allen anderen Programmiersprachen hat das Einrücken von Text eine Bedeutung. Ein Statement muss also zu Anfang einer Zeile beginnen. Es sei denn, es handelt sich um bestimmte Art von Statements, die wir noch kennenlernen werden (z.B. eine Wenn-Bedingung)
# Code beginnt am Anfang einer Zeile
var = 13
# FEHLER: Code beginnt nicht zu Anfang einer Zeile
var = 13
File "/var/folders/cj/9s881x057_12d_qyp3jcmb380000gn/T/ipykernel_10605/1894495079.py", line 2
var = 13
^
IndentationError: unexpected indent
Python gibt im obigen Beispiel eine Fehlermeldung aus. Diese signalisiert, dass der Python-Code nicht korrekt ist. Hierbei geht es nicht um inhaltliche Fehler, sondern um formale Fehler, d.h. Python kann das Statement nicht verstehen. Der Grund ist in diesem Falle ein IndentationError
, d.h. ein Fehler wegen fehlerhaften Einrückens von Text.
Hinweis: innerhalb eines Statements werden Leerzeichen hingegen ignoriert.
var = 3 + 4
var
7
Umgang mit langen Statments: lange Statements können mit “()
” über mehrere Zeilen verbunden werden. Dies bietet sich auch für die Lesbarkeit von Code an.
komplexe_rechnung = (1234
+ 12
- 13
* 14
)
komplexe_rechnung
1064
komplexe_rechnung = 1234 + 12 - 13 * 14
komplexe_rechnung
1064
Datentypen¶
Jede Variable kann unterschiedliche Datentypen annehmen. In unseren obigen Beispielen haben wir bereits einige kennengelernt.
Die Variable
zahl
hat den Wert42
angenommen.42
ist vom Typinteger
, d.h. eine GanzzahlDie Variablen
wort
undsatz
sind vom Typstr
, d.h. ein TextDie Variable
KW
ist vom Typfloat
, d.h. eine Dezimalzahl
Wir können den Datentyp einer Variable feststellen, in dem wir type
nutzen.
Beispiel:
a = 42
type(a)
int
a = 42.0
type(a)
float
Für das Programm bzw. den Computer, aber auch für uns als Datenanalyst oder Programmierer, sind Datentypen aus unterschiedlichen Gründen wichtig:
1. Speicherplatz des Datentyps
Jeder Datentyp benötigt unterschiedlich viel Speicher. So macht es für den Computer einen Unterschied, ob wir 42
oder 42.0
schreiben, da er für diese Variablen unterschiedlich viel Speicherplatz “freimacht”. Im Rahmen unserer Beispiele ist der Unterschied nicht von Bedeutung. Jedoch kann die Nutzung von Datentypen, die weniger Speicherplatz benötigen sinnvoll sein, wenn wir mit großen Datenmengen umgehen wollen. Im Rahmen dieses Kurses ist das Speicherargument jedoch nicht von großer Bedeutung.
2. Fähigkeiten des Datentyps
Jeder Datentyp hat unterschiedliche “Fähigkeiten”.3 Wir haben z.B. nicht weiter hinterfragt (bzw. es ist für uns intuitiv und logisch), dass wir die Operation “+
” mit den Datentypen integer
und float
nutzen können. Wir kennen das aus der Mathematik, von Excel oder unserem Taschenrechner. In einer Programmiersprache muss diese “Fähigkeit” jedoch “hinterlegt” sein, d.h. es muss festgelegt sein, dass dies möglich ist. Andersherum können für andere Datentypen jede Art von Fähigkeit hinterlegen - wir werden in den weiteren Kapiteln noch viele dieser Fähigkeiten kennenlernen.
Beispiel: für uns macht die Operation "Text 1"
+ "Text 2"
wenig Sinn. Die Addition von zwei Texten (hier: vom Datentyp str
) ergibt mathematisch keinen Sinn. Dennoch ist diese Operation in Python ohne Probleme möglich, weil diese - aus verschiedenen Gründen - hinterlegt ist.
text1 = "Vorname "
text2 = "Nachname"
text1 + text2
'Vorname Nachname'
Die Addition von zwei Texten verbindet die beiden Texte zu einem Text.
3. Eignung des Datentyps
Nicht jeder Datentyp ist für jede Fragestellung sinnvoll einsetzbar. So macht es keinen Sinn, dass wir Variablen, die für Berechnungen genutzt werden sollen z.B. als str
definieren. Hierdurch können sich Fehler in das Programm einschleichen ohne dass wir vor einem Fehler gewarnt werden.
Beispiel:
zahl1 = "1"
zahl2 = "2"
ergebnis = zahl1 + zahl2
ergebnis
'12'
Die Operation ist in Python erlaubt und liefert uns deshalb keinen Fehler. In unserem Fall macht das Ergebnis jedoch keinen Sinn..
Wir müssen also darauf achten, dass wir Datentypen nutzen, die für unsere Fragestellung sinnvoll sind. Außerdem müssen wir uns immer fragen, ob die Nutzung von anderen Datentypen unser Programm verbessern.
Lassen Sie uns deshalb unser Kapitalwert-Beispiel aufgreifen und andere (neue) Datentypen mit weiteren Fähigkeiten kennenlernen.
Listen¶
Der Datentyp list
(Liste) kann beliebig viele Variablen enhalten und wird mit “[ ]
” erzeugt. Auch wenn eine Liste theoretisch unterschiedliche Datentypen beinhalten kann, wird diese meist eingesetzt, um zusammenhängende Elemente zusammenzufassen (z.B. unsere Cashflows)
Beispiel:
diverses = [1, 2, "a", "d", 4.5]
diverses
[1, 2, 'a', 'd', 4.5]
zahlen = [1,14, 3, 11]
zahlen
[1, 14, 3, 11]
Auf die einzelnen Elemente der Liste (hier: Variable zahlen
) kann dann mittels eines Index zugegriffen werden:
zahl1 = zahlen[0]
zahl1
1
zahl2 = zahlen[1]
zahl2
14
Index
Der Index beginnt in Python bei allen Datentypen, die mehrere Elemente beinhalten, immer mit 0
. D.h. das erste Element befindet sich immer an Position 0
und NICHT an Position 1
.
Listen haben verschiedene Fähigkeiten. Viele dieser Fähigkeiten (die Fähigkeiten der Datentypen werden auch (Klassen-)Methoden
genannt) können sie aufrufen, in dem “.
” drücken.
Beispiel: sortieren einer Liste erfolgt via “.sort()
”
zahlen.sort()
zahlen
[1, 3, 11, 14]
In Jupyter Notebooks und in Google Colab können Sie via tab completion
, d.h. “.
” + tab
alle dieser Methoden anzeigen lassen. Hinweis: teilweise müssen Sie runterscrollen, um weitere Methoden anzeigen zu lassen.
Wir können unser Beispiel signifikant vereinfachen, in dem wir den Datentyp list
nutzen, welcher alle unsere Cashflows umfasst.
cash_flows = [-10000, 5000, 4000, 3000]
i = 0.04
KW = cash_flows[0] + cash_flows[1]/(1+i)**1 + cash_flows[2]/(1+i)**2 + cash_flows[3]/(1+i)**3
KW
1172.9062357760577
Dictionary¶
Ein weiterer sehr nützlicher Datentyp in Python ist das sog. Dictionary (dict
). Dieses können wir uns vorstellen, wie ein tatsächliches Wörterbuch. Wir können hier zu jedem Element ein passendes anderes Element abspeichern. Ein Dictionary wird mit “{}
” erzeugt. Die sogenannten key:value
-Paare werden dann im Dictionary gespeichert und können von unterschiedlichen Datentypen sein und werden via [key]
abgerufen.
Beispiel:
my_first_dict = {"Begrüßung": "Hallo", "liste_zahlen": [1,2,3,4], 2: 4.32}
Hinweis: wir können - zur besseren Lesbarkeit - das obige Beispiel auch wie folgt schreiben.
my_first_dict = {"Begrüßung": "Hallo",
"liste_zahlen": [1,2,3,4],
2: 4.32}
my_first_dict
{'Begrüßung': 'Hallo', 'liste_zahlen': [1, 2, 3, 4], 2: 4.32}
my_first_dict["Begrüßung"]
'Hallo'
my_first_dict["liste_zahlen"]
[1, 2, 3, 4]
my_first_dict[2] # Hier ist `2` kein Index, sondern ein sogenannte Schlüssel (engl. `Key``)
4.32
Auch hier können wir via tab completion
, d.h. “.
” + tab
alle Methoden anzeigen lassen.
Dictionaries eignen sich hervorragend, um Parameter und Annahmen zu speichern. Wir können unser Beispiel also weiterfassen und z.B. zwei verschiedene Szenarien rechnen:
# Szenarien und Annahmen
cf_szenario = {"base": [-10000, 5000, 4000, 3000],
"high": [-10000, 6000, 5000, 4000],
"low": [-10000, 4000, 3000, 1000],}
i = 0.04
cash_flows = cf_szenario["base"]
KW = cash_flows[0] + cash_flows[1]/(1+i)**1 + cash_flows[2]/(1+i)**2 + cash_flows[3]/(1+i)**3
KW
1172.9062357760577
cash_flows = cf_szenario["high"]
KW = cash_flows[0] + cash_flows[1]/(1+i)**1 + cash_flows[2]/(1+i)**2 + cash_flows[3]/(1+i)**3
KW
3947.9972690031846
Zusammenfassung und Ausblick¶
Wir haben unsere ersten Zeilen programmiert und dabei unsere Beispielaufgabe Schritt für Schritt verändert und optimiert. Dabei haben wir folgende Dinge gelernt:
einfache mathematische Operationen können in Python genutzt werden
es gibt einige wenige Regeln, die wir beachten müssen, um keine “technischen” Fehler zu produzieren; insbesonder müssen wir darauf achten, dass wir keine Leerzeichen an den falschen Stellen setzen
es gibt unterschiedliche Datentypen, die wir für unsere Analysen nutzen können und sollten. Nicht jeder Datentyp ist für jede Art der Problem geignet. Wir haben bisher
int
,float
,str
,list
unddict
kennengelernt. Bei diesen Datentypen handelt es sich um solche, die bereits standardmäßig in Python integriert sind (sog.build-in types
4). Wir werden im weiteren Verlauf noch sehr viel mächtigere Datentypen kennenlernen, die wir explizit für die Zwecke der Datenanalyse entwickelt wurden und sehr hilfreiche “Fähigkeiten” haben.
Im folgenden Kapitel werden wir unser Beispiel weiter optimieren. Denn - so ehrlich müssen wir sein - unsere bisherige Optimierung lässt noch keinen großen Vorteil gegenüber einem Taschenrechner und insbesondere nicht gegenüber Excel erkennen. Auch wenn wir die repetitive Definition von Cashflow-Variablen vermieden haben, ist unsere Berechnung selber noch (i) repetitiv (wir schreiben die Variable cash_flows
insgesamt 4x auf) und (ii) unflexibel, da unsere gesamte Berechnung weiterhin für jede andere Anzahl an Cashflows neu beschrieben werden müsste.
- 1
diese Formulierung ist nicht ganz korrekt, jedoch für unsere Zwecke ausreichend.
- 2
Ausnahmen sind in Python bereits belegte Wörter, sog. Keywords, diese sind hier aufgeführt keywords.
- 3
Sie können die “hinterlegten Fähigkeiten” ausgeben lassen (via:
dir(variable)
). Die Ausgabe ist für Programmieranfänger jedoch zunächst eher verwirrend und wenig hilfreich, weshalb wir an dieser Stelle nicht weiter darauf eingehen werden.- 4
siehe hier für weitere Informationen zu den
build-in types
.