2. Variablen

In jeder Programmiersprache arbeiten Sie mit Daten und Werten, die zwischengespeichert werden, damit ein Programm sinnvoll laufen kann. Diese Aufgaben übernehmen Variablen.

Beachten Sie, das die Lebensdauer von Variablen nur bis zum Programmende reicht. Sobald das Programm endet, geht der Inhalt einer Variable verloren.

Möchten Sie diese Inhalte dauerhaft speichern, so müssten Sie die Inhalte in eine Datei oder in eine Datenbank übertragen.

2.1. Grundregeln

In Python gibt es 2 einfache Regeln um mit Variablen arbeiten zu können.

Zuweisung vor der Verwendung: Jede Variable muss einem Startwert zugewiesen werden, bevor man diese in einem Ausdruck verwenden kann. Es ist nicht erlaubt x = x + 1 auszuführen, wenn x nicht vorher mit einem Wert wie x = 0 oder x = 27 deklariert wurde.

Keine Typendeklaration: In Python können Objekte jedes beliebigen Typs gespeichert werden. Python merkt sich den Typ und weiss damit, auf welche Art von Daten eine Variable verweist.

In anderen Programmiersprachen müssen Sie den Typ mit angeben, z.B. strX: string, intA: int. Dadurch sind die Variablen relativ eingeschränkt und es ist nicht möglich in ein und derselben Variable Daten unterschiedlichen Typs zu speichern.

In Python ist es viel flexiber. Sie können z.B. in der Variable x zuerst eine Zahl ( x = 1 ), später eine Zeichenkette ( x = ‚abc‘ ) und im Anschluss eine Liste ( x = [3, 2, 1] ) speichern.

ACHTUNG

Was für einen erfahrenen Programmierer nun einfach aussieht, kann für einen unerfahrenen Programmierer schwere Konsequenzen nachziehen, da man sich Werte überschreiben kann, die später genutzt werden sollten.
Daher ist es wichtig, sich für jeden Typ eine eindeutige Variable anzulegen.

2.1.1. Konstanten

Konstanten sind Variablen, in den Werte gespeichert werden, aber nicht mehr im Programmcode geändert werden können.

Python liefert keine Möglichkeit, Konstanten zu definieren. Möchten Sie eine Konstante verwenden, so können Sie eine Variable aus lauter Grossbuchstaben definieren (z.B.: MEINE_VARIABLE = 1). Aber Sie können nicht verhindern, das dieser Variable andere Werte zugewiesen werden.

2.1.2. Variablennamen

Variablennamen müssen mit Buchstaben oder einem Unterstrich beginnen. Allerdings ist der Unterstrich am Beginn von Variablennamen nur Python interne Daten vorgesehen, weswegen Sie diese in eigenen Scripten möglichst nicht verwendet werden sollten.

Die weiteren Zeichen können auch Ziffern enthalten, aber Bindestriche und Leerzeichen dürfen nicht verwendet werden. Umlaute (äöü) können verwendet werden, macht aber Programme für Programmierer aus Ländern ohne Umlaute extrem schwierig zu lesen.

Normalerweise bestehen Variablennamen aus lauter Kleinbuchstaben, Grossbuchstaben werden meist nur für Wortzusammensetzungen verwendet, z.B. einLangerVariablenname

a = 1
b = 'abc'
a = a + 1
a = c + 1                  # Fehler: An c wurde nie etwas zugeweisen

einLangerName = 1          # OK
ein_langer_name = 1        # OK
länge = 3                  # OK, aber sollte nicht verwendet werden
so geht es nicht = 5       # Fehler: Leerzeichen nicht erlaubt
so-geht-es-auch-nicht = 3  # Fehler: Nur _ Sonderzeichen erlaubt

2.2. Datentypen

Python kennt intern verschiedene vordefinierte Datentypen. Ausserdem können von Klasse, die im eigenen Code on in externen Modulen definiert sind, Objekte erzeugt werden. Dazu werden Sie später im Kapitel 11. Objectorientierte Programmierung mehr erfahren.

2.2.1. Erkennung des Datentyps

Alle Daten gelten in Python als „Objekte“ – einfache Zahlen, Zeichenketten, Listen, Tupels, Sets, Dateien und Funktionen (!) ebenso wie Instanzen, vordefinierte oder eigene Klassen.

Python verzichtet auf die in vielen anderen Programmiersprachen übliche Unterscheidung zwischen elementaren Datentypen (z.B.: Integer, Double, Boolean) und Klassen.

Dafür unterscheidet Python zwischen Variablen und Daten. Variablen sind eigentlich nur Namen, die auf Objekte verweisen, vergleichbar mit Zeigern in C, Java oder auf Links in HTML. Wenn Variablen linksseitig einer Zuweisung vorkommen ( x = … ), wird ein Verweis auf das Objekt gespeichert, das auf den rechten Ausdruck resultiert. Wenn Variablen hingegen in Ausdrücken vorkommen (rechtsseitig), ersetzt Python den Namen durch das Objekt auf das die Variable zeigt.

a = 5
x = a                   # x enthält den Wert 5

Aufgrund dieser Trennung von Variablen und Daten ist es eigentlich unmöglich den Datentyp einer Variable festzustellen. Sie können nur den Typ der Daten ermitteln. Die Variable selbst hat keinen Typ. Um nun diesen Datentyp ermitteln zu können, können Sie diesen mit type ermitteln.

x = 3; type(x)                  # <class 'int'>
x = 3.1; type(x)                # <class 'float'>
x = { 1, 2, 3 }; type(x)        # <class 'set'> 

Möchten Sie innerhalb des Programmcodes den Datentyp einer Varaible überprüfen, so ist die Methode isinstance dazu besser geeignet.

s = 'abc'
isinstance(s, str)              # True
isinstance(s, int)              # False

2.2.2. Angabe des vorgesehenen Datentyps (Type Annotation)

Seit der Python Version 3.6 ist es erlaubt, einer Variable den vorgesehen Typ anzugeben, wahlweise mit oder ohne gleichzeitiger Initialisierung der Variablen.

msg: str = 'Wichtigen Nachricht'
s: str                          # s soll später eine Zeichenkette aufnehmen
i: int = 3                      # i ist eine Integer-Variable

In anderen Programmiersprachen wären diese Daten nun an diesen Datentyp gebunden. Python dagegen hindert Sie nicht daran, ein paar Zeilen weiter eine neue Zuweisung durchzuführen, die im Widerspruch zum vorherigen Typ stehen.

i = 'abc'
s = 123

Die Datentypangaben gibt als die Möglichkeit, eine Intention syntaktisch auszudrücken. Die Informationen wird von Python aber wie ein Kommentar betrachtet.

2.2.2. Mutable oder immutable

Die einfache Frage „Was passiert bei b = a, also bei einer Zuweisung einer Variable an eine andere?“ ist nicht so trivial zu beantworten. Beginnen wir mit dem Beispiel mit ganzen Zahlen.

# Beispiel ganze Zahlen
a = 3
b  = a

In diesem Beispiel wird a der Wert 3 zugewiesen. Bei der Zuweisung b = a wird a durch den Wert 3 ersetzt. Also wird auch in b die Zahl 3 gespeichert. Um es exakter zu formulieren: a und b sind nun zwei Variablen, die beide auf ein Objekt mit der ganzen Zahl 3 verweisen.

a = 3                         # a zeigt auf die Zahl 3
b = a                         # b zeigt nun auch auf die Zahl 3
a = 4                         # a zeigt nun auf 4, b bleibt unverändert
print(a, b)                   # Ausgabe: 4, 3

Durch a = 4 wird nun a ein neuer Wert zugewiesen, a hat nun den Wert 4, b den unveränderten Wert 3.

Schauen wir uns das Besipiel 2 an. Diesen Beispiel sieht ähnlich aus, allerdings weisen wir dem Wert a nun eine Liste zu.

# Beispiel mit einer Liste
a = [ 1, 2, 3 ]
b = a
a[0] = 4
print(a, b)

Dieses Beispiel unterscheidet sich eiogentlich nur darin, das wir den ersten Wert der Liste mit 4 neu definieren. Die Ausgabe würde nun wie folgt aussehen:

[ 4, 2, 3 ] [ 4, 2 3 ]

Wie Sie erkennen können, wurde bei beiden Listen der erste Wert verändert. Warum verhält sich Python bei scheinbar zwei ganz ähnlichen Programmen so unterschiedlich?

Der Grund besteht darin, das Python zwischen veränderlichen und unveränderlichen Datentypen (mutable oder immutable) unterscheidet. Zahlen, Zeichenketten und Tupel sind immutable, d.h. eine Änderung ist unmöglich. Stattdessen wird jedes Mal, wenn ein Ausdruck neue Daten ergibt, ein neues Objekt im Speicher erzeugt.

Wenn Sie als Beispiel zuerst x = 10 und dann x = x + 1 durchführen, dann erzeugt Python ein Objekt mit dem Wert 10, dann ein neues Objekt mit dem Wert 11. Die Variable wird durch Python nun so verändert, das sie auf den neuen Platz im Speicher zeigt.

2.2.3. Veränderliche Daten kopieren

Wie geht man vor, wenn man von einer veränderlichen Liste eine unabhängige Liste benötigt, so dass zwei anfänglich gleichartigen Listen existieren?

import copy
a = [ 1, 2, 3 ]
b = copy.copy(a)           # b verweist nun auf eine unabhängige Liste
a[0] = 4                   # ändert das erste Listeneelement von a
print( a, b )              # Ausgabe: [ 4, 2, 3 ] [ 1, 2, 3 ]

Die copy Funktion erstellt also eine Kopie aus dem angegeben Objekt.

deepcopy geht noch ein Schritt weiter. Es erstellt auch Kopien aller veränderlichen Objekte, die auf das Ausgangsobjekt verweisen. Im obrigen Beispiel war deepcopy überflüssig, weil die Liste nur 3 Zahlen enthalten hatte, also unveränderliche Objekte.

Wenn eine Liste aber wieder veränderliche Objekte enthält, dupliziert deepcopy den gesamten Objektbaum. Dieses ist in der Praxis sehr aufwendig.

Ich versuche Ihnen nun anhand des nächsten Beispiels die unterschiede zwischen copy und deepcopy darzustellen.

import copy
a = [ 1, 2, [ 3, 4 ] ]         # eine verschachtelte Liste
b = copy.copy(a)
a[2][0] = 7                    # gilt trotz copy für a und b
print( a, b )                  # Ausgabe: [ 1, 2, [ 7, 4 ] ] [ 1, 2, [ 7, 4 ] ]

c = [ 1, 2, [ 3, 4 ] ]
d = copy.deepcopy(c)
c[2][0] = 7                    # gilt wegen deepcopy nur bei c
print( c, d )                  # Ausgabe: [ 1, 2, [ 7,  4 ] ] [ 1, 2, [ 3, 4 ] ]

Was passiert, wenn unterschiedliche Typen in einer Berechnung kombiniert werden, oder wenn Sie beispielsweise Zahlen in Zeichenketten umwandeln möchten oder umgekehrt?

In wenigen Fällen kümmert sich Python selbst darum, als Beispiel „Sie wollen eine ganze Zahl mit einer Flisskommazahl multiplizieren.“

a = 2                          # int
b = 2.4                        # float
c = a * b                      # ergibt auch ein float
# Ausgabe: 4.8

Von diesen Ausnahmen abgesehen müssen Sie sich selbst um den Rest kümmern. Dazu verwenden sie Funktionen, deren Namen mit dem jeweiligen Datentypen übereinstimmt.

s = 'abc'
x = 3
s = s + str(x)
# Ausgabe: abc3

In umgekehrter Richtung wandelt int und float eine Zeichenkette in eine Zahl um. Beachten Sie, dass dabei der Fehler invalid literal auftreten kann, wenn Sie versuchen die Zeichenkette ‚abc‘ in eine Zahl umwandeln.

int('123')                     # OK, die ganze Zahl 123 wurde als string                                   # definiert
float('123.3')                 # OK, die Fliesskommazahl 123 wurde als                                     # string definiert
int('abc')                     # invalid literal - abc ist keine Zahl 

2.3. Gültigkeitsbereich von Variablen

Innerhalb eines gewöhnlichen Scripts ohne Definitionen eigener Funktionen oder Klassen unterscheidet Python nicht zwischen Gültigkeitsebenen. Sobald eine Variable einmal definiert ist, kann sie weiterverwendet werden.

if 1:                          # bedeutet True und ist immer erfüllt
                               # Einrückung beachten
    x = 1                      # daher wird diese Zuweisung ausgeführt

print(x)                       # Ausgabe 1, daher OK

In Java hätten wir hier ein grosses Problem.

// nur zum Vergleich Java Code
if (true) {
    int x = 1;
}
System.out.println(x);         # Fehler, x ist hier nicht bekannt
                               # Java kennt x nur zwischen den { }

Zurück zu Python. Das folgende Beispiel sieht genauso aus wie unsere obriges Beispiel, statt dessen lösst es einen Fehler aus. Dadurch das fir if Bedingung nicht erfüllt ist, läuft das Programm bis print(x) und wirft dann einen Fehler aus.

if 0:                          # bedeutet False und ist nicht erfüllt
                               # Einrückung beachten
    x = 1                      # daher wird diese Zuweisung ausgeführt

print(x)                       # Fehler: name 'x' is not defined

Python konnte die Variable x vorab nicht finden, da Sie nur in der if Schleife definiert ist. In Python gibt es keine Möglichkeit vorab zu testen, ob eine Variable definiert ist. Man kann aber vorweg den Zustand einer Variable auf den Zustand None, im Sinne von „noch nicht festgelegt“ zuweisen.

x = None
if 0:                          # bedeutet False und ist nicht erfüllt
    x = 1                      # daher wird diese Zuweisung ausgeführt 
if x != None:
    print(x)                   # wird ebenfalls nicht ausgeführt.

Variablen, die nicht mehr benötigt werden, können mit del löschen.

x = 3
del x
print(x)                      # Ausgabe: NameError: name 'x' is not definied

Ein Sonderfall sind Funktionen und Klassen. Dort definierte Variablen gelten nur innerhalb der Funktion bzw. nur für ein Objekt der Klasse.

Weitere Informationen zu Variablen werden in den Kapiteln 9. Funktionen und 11. Objektorientierte Programmierung besprochen.

def f():                       # definiert die Funktion f
    x = 3                      # lokale Variable, nur gültig in f
    print(x)


f()                            # ruft f auf
print(x)                       # Fehler; name 'x' is not definied

2.4. Wiederholungsfragen

1.) Der folgende Code lösst einen Fehler aus. Warum?

x = 1; y = 2
print(x + y + z)

2.) Welchen Typ hat die Variable i nach der Zuweisung i = 3?

3.) Wie werden in Python Konstanten gekennzeichnet?

4.) Welche Werte gibt das folgende Programm aus?

a = 'abcde'
b = a
a = a + 'fg'
print(b)

5.) Was gibt das folgende Programm aus?

wordlist1 = [ 'Python', 'ist', 'cool' ]
wordlist2 = wordlist1
wordlist1.insert( 2, 'total' )
print(wordlist1)
print(wordlist2)

6.) Der folgende Code ist fehlerhaft. Warum? Wie könnte eine Lösung aussehen?

n = 22.7
msg = 'Die Temperatur beträgt ' + n + ' Grad.'