Datentypen – die Python-Typ-Hierarchie

Im ersten Kapitel wurden nur solche Python-Anweisungen beschrieben, die Zahlen verarbeiten, denn der Umgang mit Zahlen ist den meisten bereits aus der Schulmathematik vertraut.

Computer-Programme können aber nicht nur Zahlen, sondern auch andere Daten verarbeiten, z.B. Zeichenketten (Texte), Wahrheitswerte (wahr oder falsch) und Datenkollektionen, die aus einfachen Datenelementen zusammengesetzt sind. Eine Kollektion von Zeichenketten verwenden Sie z.B., wenn Sie einen »digitalen Notizblock« programmieren (Kapitel 14).

In diesem Abschnitt erhalten Sie einen Überblick über die wichtigsten Standard-Datentypen. In späteren Kapiteln (insbesondere Kapitel 7, 8 und 9) erfahren Sie, wie man sie in Programmierprojekten verwenden kann.

2.1  Literale und die Funktion type()

Daten müssen aufgeschrieben werden können. Eine Zeichenfolge, die einen bestimmten Wert darstellt, nennt man Literal.

Beachten Sie die feinsinnige Unterscheidung zwischen Werten und ihrer Darstellung durch Zeichen.

Beispiel: Die Zahl Eins ist ein mathematisches Objekt, ein Wert. Das Literal 1 stellt diese Zahl dar. Die gleiche Zahl kann auch durch andere Literale repräsentiert werden. So stellt das Literal 1.0 ebenfalls die Zahl Eins dar. Das können Sie in der Python-Shell nachprüfen.

 >>> 1 == 1.0
True

Der Vergleich von 1 und 1.0 liefert den Wahrheitswert True. Das heißt, die Aussage »1 ist der gleiche Wert wie 1.0« ist wahr.

Dennoch gehören die Literale 1 und 1.0 zu unterschiedlichen Datentypen. 1 gehört zum Typ int (von Englisch integer = ganze Zahl) und 1.0 gehört zum Typ float (von Englisch floating point number = Gleitkommazahl).

Mit der Funktion type() können Sie den Typ eines Objekts erfragen.

>>> type(1)
<class 'int'>
>>> type(1.0)
<class 'float'>

2.2  Die Python-Typ-Hierarchie

Python ist für seinen logischen Aufbau bekannt, der das Erlernen der Sprache erleichtert. Ein wichtiges Feature ist die sogenannte Typ-Hierarchie.

Abb. 2.1: Die Python-Typ-Hierarchie (Auszug)

Eine Hierarchie ist eine auf Überordnung und Unterordnung beruhende Ordnung. Im Fall der Typ-Hierarchie zeigt sich diese Ordnung darin, dass es für Typen, die zu einem übergeordneten Typ gehören, gemeinsame Operationen gibt. Sie kennen das bereits aus der Mathematik: Für Zahlen kennen Sie die Typen ganze Zahl (int) und Gleitkommazahl (float). Nun sind für alle Zahlen gemeinsame Operatoren (z.B. +, -, *, /) und Funktionen (z.B. round()) definiert. Sie haben »sinngemäß« die gleiche Wirkung.

Abbildung 2.1 zeigt die Datentypen, die in diesem Buch verwendet werden. Das Bild ist nicht vollständig. Es gibt noch weitere Standard-Typen, wie etwa komplexe Zahlen (complex).

2.3  Standard-Typen

2.3.1  Ganze Zahl (int)

Ganze Zahlen (Typ int) können unter Verwendung verschiedener Zahlensysteme dargestellt werden, nämlich als Dezimalzahlen, Oktalzahlen, Hexadezimalzahlen oder Binärzahlen. In diesem Buch verwenden wir aber nur die vertrauten Dezimalzahlen.

Dezimalzahlen bestehen aus den zehn Ziffern 0, 1, 2, ..., 9.

Eine Dezimalzahl (ungleich null) darf nicht mit einer führenden Null beginnen. Eine Ziffernfolge wie 09 liefert eine Fehlermeldung.

Ganze Zahlen dürfen beliebig lang sein.

2.3.2  Gleitkommazahl (float)

Eine Gleitkommazahl (Typ float) kann (wie bei einem wissenschaftlichen Taschenrechner) als Dezimalbruch oder in Exponentialschreibweise dargestellt werden.

Ein Dezimalbruch (»Kommazahl«) besteht aus einer Ziffernfolge mit einem Punkt, der dem deutschen Komma entspricht.

Gültige Gleitkommazahlen sind 3.14 oder .45 oder 0.23 oder 2.0, nicht aber 2 (Punkt fehlt).

Für Zahlen, die sehr nahe bei null liegen oder sehr groß sind, wird die Exponentialschreibweise verwendet, die Sie auch von einem wissenschaftlichen Taschenrechner kennen.

Ein float-Literal in Exponentialschreibweise besteht aus einer Zahl, gefolgt von dem Buchstaben e oder E, einem Vorzeichen (+ oder -), das bei positiven Exponenten auch weggelassen werden kann, und schließlich einer ganzen Zahl als Exponenten.

Gültige Literale sind:

1.0 e-3 entspricht der Zahl 1*10-3 bzw. 0.001

2.1 E+2 entspricht der Zahl 2,1 * 102 bzw. 210

Ungültig sind:

0.1-E7 Minuszeichen vor dem E

1.2e0.3 keine ganze Zahl als Exponent

1E keine Zahl als Exponent

Die Genauigkeit der internen Darstellung von Gleitkommazahlen ist auf eine feste Anzahl von Stellen begrenzt. Gibt man längere Ziffernfolgen ein, so werden die letzten Stellen einfach abgetrennt.

>>> 1.2345678901234567890
1.2345678901234567

2.3.3  Zeichenkette (str)

Eine Zeichenkette ist eine Folge von Zeichen aus einem Alphabet. Man bezeichnet sie auch als String (englisch für Schnur oder Kette).

Eine Zeichenkette beginnt und endet entweder mit einfachen oder mit doppelten Anführungszeichen.

Beispiele: 'Python' oder "Python". Nicht erlaubt ist, vorne und hinten unterschiedliche Anführungszeichen zu verwenden, wie z.B. in "Python'.

Wenn ein String in einfache Anführungszeichen eingefasst ist, dürfen in seinem Innern doppelte Anführungszeichen vorkommen.

Beispiel:

 'Sie sagte "Danke" und ging hinaus.'

Umgekehrt geht es auch:

 "Sie sagte 'Danke' und ging hinaus."

Zeichenketten sind nicht änderbar. Das heißt, man kann in einem String-­Objekt keine Buchstaben einfügen, entfernen oder ändern.

In einem Python-Programm darf eine Zeichenkette normalerweise nicht über eine Zeile hinausgehen. Es gibt aber eine besondere Schreibweise für lange Zeichenketten.

Wenn eine Zeichenkette mit drei Anführungszeichen beginnt und endet, darf sie über beliebig viele Zeilen gehen.

Beispiel:

 '''Die Ewigkeit dauert lange,
besonders gegen Ende. (Woody Allen) '''

Python bietet eine Fülle spezieller Operationen für Zeichenketten. Kapitel 9 widmet sich diesem Thema.

2.3.4  Tupel (tuple)

In einem Tupel sind mehrere Objekte gleicher oder unterschiedlicher Typen zusammengefasst. Das Literal eines Tupels beginnt und endet mit runden Klammern. Beispiele:

person = ('Anna', 2001)
ort = ('D', '10119',' Berlin')
rot = (255, 0, 0)

Tupel sind nicht änderbar. Mit Tupeln kann man die Struktur von Objekten der Wirklichkeit modellieren. Die drei Beispiel-Tupel sind Modelle folgender Strukturen:

  • Name und Geburtsjahr einer Person
  • Eindeutige Ortsbezeichnung durch Länderkürzel, Postleitzahl und Name des Ortes
  • Beschreibung einer Farbe durch Angabe von Rot-, Grün- und Blaukomponente

Ein Tupel mit einem einzigen Element muss ein Komma enthalten, damit es von einem Ausdruck mit Klammern – wie z.B. (1) – unterschieden werden kann.

(1,)  

2.3.5  Liste (list)

Eine Liste ist eine änderbare Sequenz von Objekten beliebiger Typen. Das Literal einer Liste beginnt und endet mit eckigen Klammern. Dazwischen werden – durch Kommas getrennt – die Items der Liste aufgeführt.

primzahlen = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
freunde = ['Tina', 'Max', 'Sven']

Meist verwendet man Listen zur Aufzählung von Objekten eines Typs, etwa eine Liste von Zahlen oder eine Liste von Strings.

Im Unterschied zu Strings und Tupeln kann man eine Liste verändern: Man kann zum Beispiel das erste Objekt durch einen neuen Wert ersetzen. Probieren Sie das in der Python-Shell aus!

>>> s = [3, 7, 13]
>>> s [0] = 5
>>> s
[5, 7, 13]

2.3.6  Menge (set)

Mengen sind ungeordnete Kollektionen ohne Duplikate. Das heißt, die Elemente einer Menge haben keine besondere Reihenfolge und jedes Element kommt nur ein einziges Mal vor.

Python bietet zur Repräsentation von Mengen den Typ set. Ein Objekt vom Typ set erzeugen Sie, indem Sie – wie in der Mathematik – die Elemente in geschweiften Klammern aufzählen:

{1, 2, 3}

Eine leere Menge wird nicht wie in der Mathematik durch {} dargestellt, sondern durch den Ausdruck set(). Der Ausdruck {} liefert ein leeres Dictionary.

2.3.7  Dictionary (dict)

Ein Dictionary (englisch für Wörterbuch) besteht aus Paaren der Form schlüssel:wert, die zwischen zwei geschweiften Klammern stehen und durch Kommas getrennt sind.

Beispiel:

 >>> d = {'sun’:’Sonne’, 'moon’:’Mond’, 'star’:’Stern’}

Zwischen den zwei Komponenten eines Paares steht ein Doppelpunkt. Der Ausdruck vor dem Doppelpunkt wird als Schlüssel (key) bezeichnet, der dahinter als Wert (value). Der Schlüssel ermöglicht den Zugriff auf den Wert. Man schreibt den Schlüssel in eckigen Klammern hinter den Namen des Dictionarys.

Beispiel:

 >>> d['moon']
'Mond'

Ein Dictionary funktioniert wie das menschliche Gedächtnis. Wenn ich mich frage, was das englische Wort »moon« auf Deutsch heißt, gehe ich nicht in Gedanken meinen gesamten englischen Wortschatz durch, um irgendwann auf das Wort und seine Übersetzung zu stoßen. Vielmehr ist der Begriff »moon« in meinem Gedächtnis direkt mit dem Wort »Mond« assoziiert. Sofern ich die Vokabel kenne, weiß ich augenblicklich die Übersetzung.

2.3.8  Wahrheitswerte – der Datentyp bool

Eine Aussage wie »es regnet gerade« kann wahr oder falsch sein. Die beiden Wahrheitswerte wahr und falsch werden durch die Literale True und False dargestellt. Beachten Sie die Schreibweise! True und False beginnen jeweils mit Großbuchstaben.

Eine Besonderheit bei Python ist, dass alle Objekte einen Wahrheitswert ­tragen:

  • Leere Kollektionen, z.B. der leere String '' oder die leere Liste [], und Zahlen mit dem Wert null besitzen den Wahrheitswert False.
  • Nicht leere Kollektionen und alle Zahlen ungleich null besitzen den Wahrheitswert True.

Mit einem Aufruf von bool() können Sie den Wahrheitswert eines Objekts ermitteln:

>>> bool(123)
>>> True
>>> bool(0)
>>> False

Die Bezeichnung bool erinnert an den englischen Mathematiker George ­Boole, der im Jahre 1854 erstmals eine mathematische Theorie logischer Formeln veröffentlichte.

Wahrheitswerte spielen bei bedingten Anweisungen eine Rolle. Mehr dazu finden Sie in Kapitel 4.

Die Standard-Typen, die in diesem Kapitel beschrieben werden, gehören zur »Grundausstattung« von Python. Sie können aber weitere Typen importieren (siehe Kapitel 6) oder selbst neue Typen definieren (siehe Kapitel 13).

2.4  Gemeinsame Operationen für Kollektionen

Die Typ-Hierarchie vereinfacht das Programmieren, weil man bei Typen, die zu einer Kategorie gehören, gleiche Bezeichnungen für gleiche oder vergleichbare Operationen verwenden kann. Das hilft vor allem bei der Arbeit mit Kollektionen, für die es sehr viele Operationen gibt.

2.4.1  Kollektion

Eine Kollektion ist eine Zusammenfassung von mehreren einzelnen Daten zu einer Gesamtheit. Ein Beispiel für eine Kollektion ist eine Zeichenkette. Sie besteht aus einer beliebigen Anzahl von einzelnen Zeichen.

Die einzelnen Datenelemente einer Kollektion nennt man Items oder Elemente. Eine Kollektion, bei der die Items in einer bestimmten Reihenfolge angeordnet sind, nennt man Sequenz. Beispiele für Sequenzen sind: Zeichenkette, Tupel und Liste. Dagegen haben die Elemente einer Menge oder eines Dictionarys keine bestimmte Reihenfolge.

Es gibt einige Operationen, die auf alle Kollektionen angewendet werden ­können.

Test auf Vorkommen

Mit dem Operator in kann man prüfen, ob ein bestimmtes Element in einer Kollektion enthalten ist.

>>> 'I' in 'Team'
False
>>> 1 in {1, 2, 3}
True

Anzahl der Items

Die Standard-Funktion len() liefert die Größe einer Kollektion, genauer: die Anzahl der enthaltenen Items. Beispiele:

>>> len('Python')
6
>>> len([1, 2])
2

Iteration

Alle Arten von Kollektionen kann man für Iterationen verwenden. In einer Iteration werden alle Items einer Kollektion durchlaufen und in irgendeiner Form verarbeitet. Mehr zu Iterationen in Kapitel 4.

2.4.2  Sequenz

Für Sequenzen (String, Liste, Tupel) gibt es speziellere Operationen, für die die Reihenfolge der Items von Bedeutung ist.

Index

Die Items einer Sequenz sind durchnummeriert. Die Nummerierung beginnt bei 0. Das erste Item hat den Index 0, das zweite hat den Index 1 und so weiter.

Man kann auf ein einzelnes Element zugreifen, indem man hinter dem Namen der Sequenz in eckigen Klammern den Index angibt.

Beispiele:

 >>> s = ('rot', 'gelb', 'grün')
>>> s[1]
'gelb'

Verwendet man negative Indexe, so wird von hinten gezählt. Ist s der Name einer Sequenz, so ist s[-1] das letzte Element, s[-2] das vorletzte usw.

>>> s[-1]
'grün'

Konkatenation

Mit dem Plus-Operator + kann man zwei Sequenzen aneinanderhängen. Diese Operation nennt man auch verketten oder konkatenieren. Dadurch entsteht eine neue, längere Sequenz. Die Konkatenation funktioniert nur mit gleichartigen Sequenzen. Man kann also nur Strings mit Strings konkatenieren, Tupel mit Tupel und Listen mit Listen. Probieren Sie einige Konkatenationen in der Python-Shell aus:

>>> [1, 2, 3] + [5, 7]
[1, 2, 3, 5, 7]
>>> 'Abend' + 'rot'
'Abendrot'
>>> ('Tom', 1998) + ('Berlin',)
('Tom', 1998, 'Berlin')
>>> [1, 2, 3] + [5, 7]
[1, 2, 3, 5, 7]

Für Mengen ist der Plusoperator nicht definiert. Denn eine Menge ist keine Sequenz. Die Elemente einer Menge sind in keiner bestimmten Reihenfolge, deshalb ergibt das Konzept des Verkettens keinen Sinn.

2.5  Objekte eines Typs erzeugen – Casting

Das Literal 123 ist eine ganze Zahl, ein Objekt vom Typ int. Dagegen ist '123' eine Zeichenkette, die wie eine Zahl aussieht. Mit einem Aufruf von int() können Sie aus einer Zeichenkette eine ganze Zahl gewinnen:

>>> s = '123'
>>> zahl = int(s)
>>> zahl
123

Eine solche Operation, die Gewinnung eines Objekts aus einem Objekt anderen Typs, nennt man Casting. Manchmal wird auch von »Typumwandlung« gesprochen. Man sagt: »Eine Zeichenkette wird in eine Zahl umgewandelt.« Aber streng genommen wird kein Objekt umgewandelt, sondern es wird ein neues Objekt des gewünschten Typs erzeugt.

In gleicher Weise können Sie auch aus anderen Objekten eine ganze Zahl gewinnen:

>>> int(12.3)
12
>>> int(False)
0

So wie bei den ganzen Zahlen können Sie auch die anderen Typen wie Funktionen aufrufen und neue Objekte erzeugen.

Mit str() erzeugen Sie aus einer Zahl oder einem anderen Objekt einen String:

>>> str(123)
'123'
>>> str([1, 2, 3])
'[1, 2, 3]'

Als Faustregel gilt: Das Casting funktioniert nur dann, wenn es sinnvoll ist. So kann man aus einer beliebigen Kollektion eine Liste erzeugen:

>>> list({1, 2, 3})
[1, 2, 3]
>>> list('Sonne')
['S', 'o', 'n', 'n', 'e']

Mit einer Zahl dagegen gelingt das Casting nicht:

>>> list(123)
Traceback (most recent call last):
File "<pyshell#99>", line 1, in <module>
list(123)
TypeError: 'int' object is not iterable

Mit set() gewinnen Sie aus einer beliebigen Kollektion eine Menge. Dabei werden Duplikate entfernt.

>>> set([1, 2, 1, 1])
{1, 2}
>>> set('abaac')
{'a', 'c', 'b'}

2.6  Dynamische Typisierung

Dieser Abschnitt ist vor allem für Leserinnen und Leser, die bereits andere Programmiersprachen kennen.

Eine Besonderheit von Python gegenüber Java oder C++ ist die dynamische Typisierung. Bei einer Zuweisung wie

a = 1 

wird ein Name (a) an ein Objekt (die Zahl 1) gebunden. Fertig. Das Objekt gehört zwar zu einem Typ (hier: int). Aber der Typ wird nicht an einen Namen gekoppelt. Jedem Objekt »sieht man an«, zu welchem Typ es gehört. Beispiel: Eine Ziffernfolge ohne Punkt wird immer als Objekt vom Typ int (ganze Zahl) interpretiert. Bei Programmiersprachen mit einer statischen Typisierung ist das anders. Bei Java oder C++ muss jede Variable deklariert werden. Dabei wird dem Namen (dauerhaft) ein Typ zugeordnet. In der Java-Anweisung

int a = 1;

wird der Name a dem Typ int (ganze Zahlen) zugeordnet und mit dem Wert 1 belegt.

Die dynamische Typisierung von Python hat einige Vorteile. Insbesondere werden Programmtexte kürzer und einfacher. Ein Nachteil ist, dass bestimmte logische Fehler im Programmtext nicht automatisch erkannt werden.

2.7  Übung: Anweisungen

Welche Ergebnisse liefern die folgenden Anweisungen in der Python-Shell? Tragen Sie die Ausgabe jeweils in die leere Zeile unter der Anweisung ein.

>>> s = [('a', 1), ('b',2)]
>>> len(s)

>>> s[0]

>>> s[0][0]

>>> len([])

>>> 'Tag ' + str(1)

>>> stadt = 'Dortmund'
>>> stadt[0] + stadt[1]

>>> len(set('aaab'))

>>> bool([] + [])