3. Standard Datentypen

In den vorigen Kapiteln wurden einführende Themen behandelt und erste Eindrücke von Python gewonnen. In den folgenden Kapiteln wird die Programmiersprache Python systematisch aufgearbeitet.

Obwohl hier auf Python fokusiert wird, sind die vorgestellten Techniken in anderen Programmiersprachen ähnlich.

3.1. Datentypen im Überblick

Eine Variable muss wissen welchen Datentyp sie speichern soll um entsprechend Speicher zu allozieren (Char, Integer, Gleitkomma, ...).

Die folgende Abbildung zeigt Datentypen in Python im Überblick. Daraus werden in den folgenden Kapiteln die wichtigsten im Detail behandelt.

_images/datentypen.png

Datentypen in Python

Generell unterscheidet man zwischen:

  • Zahlen
  • Kollektionen
  • Bool’schen Variablen
  • None Type

3.2. Wertzuweisung

Datentypen sind im Wesentlichen Objekte (Instanzen) welche bestimmte Daten aufnehmen können. Die Anweisung:

a = 342

bewirkt eine Wertzuweisung (siehe Abbildung Schaubild einer Wertzuweisung).

_images/referenz.png

Schaubild einer Wertzuweisung

Genauer gesagt:

  • einem Objekt (Instanz) vom Typ int (Integer) wird
  • ein Speicherplatz mit der Identität 28609680 (Speicherplatznummer, Adresse)
  • und der Wert 342 zugewiesen.
  • Dieses Integer Objekt (“Box”) bekommt den Variablennamen a welcher aus Literalen besteht.

Vereinfacht nennt man das Ganze: die Variable a.

Literale:

  • Das sind Zeichenfolgen, die nach bestimmten (zulässigen) Regeln aufgebaut sind.
  • Werte werden durch Literale dargestellt.

Beispiele

  • Wahrheitswerte: True, False
  • Ganzzahlen: 13, -34
  • Gleitkommazahlen: 12.45, -12.3E08
  • Zeichenketten: "Ein Text so", 'oder so'

3.2.1. Anweisung id() und type()

Der Datentyp und die Identität einer Variablen kann mittels type() und id() abgefragt werden:

In [1]: a = 342

In [2]: a
Out[2]: 342

In [3]: type(a)
Out[3]: int

In [4]: id(a)
Out[4]: 2189018132976

Die Identität (Speicherplatzadresse) ändert sich bei jedem Aufruf des Skripts da ein anderer Speicherplatz belegt wird.

3.2.2. Laufzeitmodell

Darunter versteht man wie Python Variablen zur Laufzeit verwaltet.

Statische Typisierung

Bei Programmiersprachen wie Java, C++ muss eine Typisierung von Hand vorgenommen werden (=statisch) d.h.:

int x = 15;

Eine Laufzeitänderung des Typs kann nur mit einem cast erfolgen. Z.B.

float *b = static_cast<float*>(a);
Dynamische Typisierung

In Python ist keine explizite Typisierung notwendig. Diese wird automatisch zur Laufzeit vorgenommen. Man spricht von dynamischer Typisierung. Beispiel

a = 5        # Variable a ist eine Ganzzahl (int) Objekt
a = "ok"     # Python "loescht" das int Objekt und
             # Variable a ist nun ein string Objekt

Warnung

Dynamische Typisierung ist elegant aber gefährlich da sich der Datentyp während der Laufzeit ändern kann!

Hier ein Beispiel:

In [1]: x = 15       # Typ int

In [2]: x = 'Hansi'  # Typ von int -> string

In [3]: x / 2
Traceback (most recent call last):

  File "<ipython-input-3-75a19068da4d>", line 1, in <module>
    x / 2

TypeError: unsupported operand type(s) for /: 'str' and 'int'

Variable: Kopie und Zeiger

Es gibt 2 Variablentypen: Kopien (klassische Variable) oder Zeiger (Referenz oder Pointer). Kopien werden vereinfacht als “Variable” bezeichnet. Zeiger gerne als Zeigervariable.

Variablen bzw. Zeiger auf Variablen gibt es in allen Programmiersprachen. In C++ wird dies in der Deklaration explizit angegeben:

int x = 15;  // Variable (Kopie)
int *x;      // Zeigervariable durch * gekennzeichnet

Die Abbildung Variable und Zeiger erklärt den Unterschied grafisch:

_images/Zeiger.png

Erklärungen:

  • Die Variablen va, vb (Kopien) befinden sich tatsächlich im Speicher und belegen entsprechend Platz.
  • Zeigervariable za, zb hingegen, speichern nur die Adresse (Id), wo sich eine Variable befindet.
  • Zeiger “zeigen” auf die Variable und belegen bei der Erzeugung keinen Speicherplatz für den Wert! Dieser muss i.A. separat alloziert werden.

Python Variablen können sich :

  • wie Variablen (Kopien) aber auch wie Zeigervariablen verhalten.
  • Welche Art Python verwendet, hängt mit den Datentypen in Python zusammen.

Generell unterscheidet man 2 Python Datentypen:

  • unveränderbare im Sinne des belegten Speicherplatzes z.B. Zahlen (int, float, complex) sowie tuple, string
  • veränderbare im Sinne des belegten Speicherplatzes z.B. list, dict, set

Diese Unterscheidung ist essentiell für das Verstehen der Referenzierung in Python (Variablen oder Zeigerverhalten) Generell gibt es 2 Regeln:

  • unveränderbar: Es wird ein neuer Speicherplatz belegt, sobald eine neue Wertzuweisung erfolgt. D.h. zuerst Zeigervariable, danach klassische Variable (Kopie).

    Erklärung am Beispiel:

    In [1]: a = 342       # belege Speicher mit Zahl und erzeuge Zeiger a
    
    In [2]: b = a         # zeige mit b auf a, b ist ein weiterer Zeiger!
    
    In [3]: id(a), id(b)  # es wurde kein neuer Speicher angelegt...
    Out[3]: (2187003088144, 2187003088144)
    
    In [4]: b = 265       # belege Speicher mit Zahl und verknuepfe mit b
    
    In [5]: id(a), id(b)  # Kopie da neuer Speicher angelegt ...
    Out[5]: (2187003088144, 2187003088624)
    
  • veränderbar: Trotz Wertzuweisung bleibt der Speicherplatz der Gleiche d.h. typisches Zeigerverhalten.

    Daher Vorsicht, bei Listen, Dictionaries,...:

    In [1]: a = [1,2,3]          # definiere a
    
    In [2]: b = a                # b zeigt auf a
    
    In [3]: b[1]=5               # b noch immer Zeiger, aendert auch a!
    
    In [4]: b
    Out[4]: [1, 5, 3]            # Veraenderung von b
    
    In [5]: a
    Out[5]: [1, 5, 3]            # AUCH Veraenderung von a!
    

    Abhilfe schafft hier nur explizites Kopieren:

    In [1]: a = [1,2,3]
    
    In [2]: b=a[:]          # explizites Kopieren
    
    In [3]: b[1]=5
    
    In [4]: b
    Out[4]: [1, 5, 3]       # Veraenderung von b
    In [5]: a
    Out[5]: [1, 2, 3]       # keine Veraenderung von a
    

3.2.3. NoneType

In Python kann eine Variable :
  • noch nicht definiert sein
  • über eine Wertzuweisung Name + Wert (Typ) haben
  • oder den Typ None besitzen

Beispiele:

In [1]: b             # Variable nicht definiert
Traceback (most recent call last):

  File "<ipython-input-1-89e6c98d9288>", line 1, in <module>
    b

NameError: name 'b' is not defined


In [2]: b = None      # Variable definiert mit dem Wert "nichts"

In [3]: b             # keine Ausgabe nach ENTER!

In [4]: b = 2

In [5]: b             # Variable definiert, Wert = 2
Out[5]: 2

Dieser None Typ kann sehr hilfreich sein, z.B. beim Setzen von Defaultwerten (genaueres später).

3.2.4. Bezeichner (identifiers)

Darunter versteht man die zulässigen Variablennamen:

identifiers ::= (letter | "_") (letter | digit | "_")

letter ::=   "a"..."z" | "A"..."Z"
digit  ::=   "0"..."9"

dabei heißt ::= definiert als, | heißt oder.

Beispiele für Bezeichner:

In [1]: Karl93 = 39       # ok

In [2]: _name3 = 'Susi'   # ok

In [3]: 12Sigma = 4.34    # nicht erlaubt!
  File "<ipython-input-3-513d4307d796>", line 1
    12Sigma = 4.34    # nicht erlaubt!
          ^
SyntaxError: invalid syntax

Unterstriche

Unterstriche haben teilweise “magisches Verhalten” wie

  • doppelte Unterstriche (z.B. __doc__, __init__)
  • ein Unterstrich bei Klassendefinitionen (z.B. _name)

mehr dazu später.

Reservierte Namen

Wie in jeder Programmiersprache gibt es auch in Python reservierte Schlüsselwörter welche nicht als Bezeichner verwendet werden dürfen.

False    class      finally   is         return
None     continue   for       lambda     try
True     def        from      nonlocal   while
and      del        global    not        with
as       elif       if        or         yield
assert   else       import    pass
break    except     in        raise

3.3. Wahrheitswerte

Wahrheitswerte sind Variablen mit zwei Zuständen (0/1, wahr/falsch). Für diese gilt:

  • Literale in Python sind True oder False.
  • Man kennt diese als Datentyp bool.
  • In Python sind die Werte 1/True bzw. 0/False zugeordnet.

Beispiele:

In [1]: 12 > 11
Out[1]: True

In [2]: antwort = ( 2*3 == 6 )

In [3]: antwort
Out[3]: True

In [4]: type(antwort)
Out[4]: bool

In [5]: antwort + antwort
Out[5]: 2

3.4. Ganze Zahlen

Ganze Zahlen sind positive oder negative Zahlen. Für diese gilt:

  • diese können Dezimal-, Oktal-, Hexadezimal-, Binärzahlen sein.
  • und sind bekannt als Datentyp int (Integer).

Beispiele:

In [1]: 127      # Dezimalzahl
Out[1]: 127

In [2]: 0b11011  # Binärzahl beginnt mit 0b
Out[2]: 27

In [3]: 0x1af    # Hexadezimalzahl beginnt mit 0x
Out[3]: 431

Beachte: Die Ausgabe der Zahlen erfolgt immer als ganze Dezimalzahl.

3.5. Gleitkommazahlen

Gleitkommazahlen sind positive oder negative Zahlen mit einem “Komma”. Für diese gilt:

  • Darstellung als Gleitkommazahlen 31.4, -0.00673
  • oder Exponentialzahl 0.314E+2, -673.e-05 und
  • sind bekannt als Datentyp float.

Beispiele:

In [1]: 12398741634341798.132
Out[1]: 1.2398741634341798e+16

In [2]: 0.0000000000234234
Out[2]: 2.34234e-11

3.6. Komplexe Zahlen

Komplexe Zahlen bestehen aus einem Real- und Imaginärteil. Für diese gilt:

  • Imaginärteil wird mit dem Suffix j oder J angegeben.
  • Anteile einer komplexen Zahl z werden ausgewählt mit: z.real und z.imag .
  • Diese sind bekannt als Datentyp complex.

Beispiele:

In [3]: a = 2 + 3j

In [4]: b = 1 - 1j

In [5]: c = a*b

In [6]: c
Out[6]: (5+1j)

In [7]: c.real
Out[7]: 5.0

In [8]: c.imag
Out[8]: 1.0

3.7. Operatoren für Zahlen

Arithmetische Operatoren

In [1]: -1             # negatives Vorzeichen
Out[1]: -1

In [2]: +1             # positives Vorzeichen
Out[2]: 1

In [3]: 2 + 3          # Addition
Out[3]: 5

In [4]: 2 - 3          # Subtraktion
Out[4]: -1

In [5]: 2.0 * 3        # Multiplikation
Out[5]: 6.0

In [6]: 3 / 2          # Division
Out[6]: 1.5

In [7]: 5 // 3         # Ganzzahldivision
Out[7]: 1

In [8]: 5 % 3          # Rest einer Ganzzahldivision
Out[8]: 2

In [9]: 2 ** 3         # Potenz
Out[9]: 8

In [10]: 4 ** (1/3.)   # Wurzel
Out[10]: 1.5874010519681994

Bemerkung

Zahlentypen werden durch Operation verändert. Aus float wird int oder umgekehrt je nach Rechenoperation!

Boolsche Operatoren

In [1]: 2 > 1            # größer als, "<" kleiner als
Out[1]: True

In [2]: 3 >= 4           # größer gleich als
Out[2]: False

In [3]: 3 == 4           # vergleicht beide Werte "gleich", Achtung
Out[3]: False

In [4]: 3 != 4           # vergleicht beide Werte "nicht gleich"
Out[4]: True

Achtung die Operation == (vergleicht Werte) entspricht nicht is (vergleicht Identifier id(..)). Beispiel:

In [1]: a = [5]

In [2]: b = [5]

In [3]: a is b           # Listen haben unterschiedliche Identifier id(..)
Out[3]: False

In [4]: a == b           # aber gleichen Wert
Out[4]: True

In [5]: a = b            # a und b "zeigen" jetzt auf gleichen Speicherplatz

In [6]: a is b           # und haben deshalb den gleichen Identifier id(..)
Out[6]: True

In [7]: a == b           # und natuerlich den gleichen Wert
Out[7]: True

Kombination aus Zuweisung und Operator

In [1]: a = 2            # a ist 2

In [2]: a += 1           # addiere 1 zu a (ergibt 3), setze Ergebnis auf a

In [3]: a
Out[3]: 3

In [4]: a *= 2           # 2 mal a, setze neues Ergebnis auf a

In [5]: a
Out[5]: 6

In [6]: a -= 2           # -2 zu a, setze neues Ergebnis

In [7]: a
Out[7]: 4

3.8. Sequenzen

Sequenzen sind eine Kollektion einer Folge von Objekten (Elemente oder engl. items). Eigenschaften:

  • Jedes Element besitzt einen Index (Start bei 0, Letztes -1).
  • Typische Datentypen: Listen, Tuple, Strings
  • Abbildung Graphische Darstellung einer Sequenz zeigt eine Sequenz grafisch:
_images/sequenz.png

Graphische Darstellung einer Sequenz

Methoden

Vorab einige Beispiele:

In [1]: s = "Dies ist unser Teststring"

In [2]: 'u' in s              # prueft ob 'u' in Sequenz enthalten ist
Out[2]: True

In [3]: s += " mit Punkt."    # Verkettung beider Sequenzen

In [4]: s[2:8]                # Ausschnitt von Index 2 bis 8 (exklusive)
Out[4]: 'es ist'

In [5]: len(s)                # Laenge der Sequenz, Anzahl der Elemente
Out[5]: 36

Für alle sequenziellen Datentypen sind folgende Operationen definiert (siehe Tabelle Methoden von Sequenzen).

In dieser Tabelle gilt:

  • s und t sind Instanzen desselben sequenziellen Datentyps (z.B. Liste, String, ...).
  • i, j, k und n sind Ganzzahlen (z.B. 1,2,3).
  • x ist eine Referenz auf eine beliebige Instanz des sequenziellen Datentyps (z.B. Ganzzahl, Buchstabe)
Methoden von Sequenzen
Notation Beschreibung
x in s Prüft, ob x in s enthalten ist. Das Ergebnis ist eine bool-Instanz.
x not in s Prüft, ob x nicht in s enthalten ist. Das Ergebnis ist eine bool-Instanz. Gleichwertig mit not x in s.
s + t Das Ergebnis ist eine neue Sequenz, die eine Verkettung von s und t enthält.
s += t Erzeugt die Verkettung von s und t und weist diese s zu.
s*n oder n*s Liefert eine neue Sequenz, die die Verkettung von n Kopien von s enthält.
s*= n Erzeugt das Produkt s*n und weist dieses s zu.
s[i] Liefert das i-te Element von s.
s[i:j] Liefert den Ausschnitt aus s von i bis j.
s[i:j:k] Liefert den Ausschnitt aus s von i bis j, wobei nur jedes k-te Element beachtet wird.
len(s) Gibt eine Ganzzahl zurück, die die Anzahl der Elemente von s angibt.
min(s) Liefert das kleinste Element von s, sofern eine Ordnungsrelation für die Elemente definiert ist.
max(s) Liefert das größte Element von s, sofern eine Ordnungsrelation für die Elemente definiert ist.

3.8.1. Liste

Listen sind:
  • veränderbare (mutable) Sequenzen
  • können beliebige Datentypen enthalten (auch Listen)
  • werden in eckige Klammern gesetzt [ .. ]

Beispiele:

In [1]: [1,2,3,4]                            # Definition der Liste aus Zahlen
Out[1]: [1, 2, 3, 4]

In [2]: namen = ['Hans', 'Karl', 'Franz']    # Definition der Liste aus Strings

In [3]: print(namen)
['Hans', 'Karl', 'Franz']

In [4]: print(len(namen), namen[1])          # Sequenzmethoden, siehe oben
3 Karl

In [5]: position = ["A", [0.3, 1.4, 2.6]]    # Gemischte Liste

Methoden

In der folgenden Tabelle sind s und t Listen, i, j und k sind Ganzzahlen. x ist eine beliebige Instanz. Die eckigen Klammern [ ] in der Tabelle bedeuten, dass dieser Eintrag optional ist (siehe Tabelle Methoden von Listen).

Methoden von Listen
Methode Wirkung
s.append(x) Hängt Element x ans Ende von s an.
s.extend(t) Hängt alle Elemente von t ans Ende von s an.
s.count(x) Gibt an, wie oft das Element x in s vorkommt.
s.index(x[, i[, j]]) Gibt den Index k des ersten Vorkommens von x im Bereich i <= k < j zurück.
s.insert(i, x) Fügt x an der Stelle i in s ein. Anschließend hat s[i] den Wert von x, wobei alle folgenden Elemente um eine Stelle nach hinten aufrücken.
s.pop([i]) Gibt das i-te Element von s zurück und entfernt es aus s. Ist i nicht angegeben, wird das letzte Element genommen.
s.remove(x) Entfernt das erste Vorkommen von x aus der Sequenz s.
s.reverse() Kehrt die Reihenfolge der Elemente in s um.
s.sort() Sortiert s.

Weitere Beispiele:

In [1]: l = [1, 2, 3]

In [2]: l.extend([2, 4, 6])

In [3]: l
Out[3]: [1, 2, 3, 2, 4, 6]

In [4]: l.count(2)
Out[4]: 2

In [5]: l.index(3)
Out[5]: 2

In [6]: l.pop()
Out[6]: 6

In [7]: l
Out[7]: [1, 2, 3, 2, 4]

In [8]: l.sort()

In [9]: l
Out[9]: [1, 2, 2, 3, 4]

Bei Listen können auch alle Methoden von Sequenzen verwendet werden.

3.8.2. Zeichenketten (Strings)

Zeichenketten sind:
  • Folgen von Zeichen (characters)
  • nicht änderbar (z.B. keine Zeichen entfernbar)
  • kurze Zeichenketten starten mit " oder '
  • lange Zeichenketten starten mit """
  • können mit + zusammengesetzt werden
  • bekannt als Datentyp str (string)

Beispiele:

In [1]: name = "Hans Mayer"

In [2]: name
Out[2]: 'Hans Mayer'

In [3]: name = "Hans \
   ...: Mayer"

In [4]: name
Out[4]: 'Hans Mayer'

In [5]: name = """Hans
   ...: Mayer"""

In [6]: name
Out[6]: 'Hans\nMayer'

In [7]: type(name)
Out[7]: str

Bei Zeichenketten können auch alle Methoden von Sequenzen verwendet werden.

Steuerzeichen

Tabelle String Steuerzeichen fasst typische Steuerzeichen speziell für Zeichenketten zusammen.

String Steuerzeichen
Escape-Sequenz Bedeutung
\f Formfeed (FF) erzeugt einen Seitenvorschub.
\n Linefeed (LF) setzt die Ausgabeposition in die nächste Zeile.
\r Carriage Return (CR) setzt die Ausgabeposition an den Anfang der nächsten Zeile.
\t Horizontal Tab (TAB) hat die gleiche Bedeutung wie die Tabulatortaste.
\” Doppeltes Hochkomma
\’ Einfaches Hochkomma
\ \ Backslash, der wirklich als solcher in dem String erscheinen soll

Beispiele:

In [1]: print("Ein Satz\n mit Zeilenumbruch")
Ein Satz
 mit Zeilenumbruch

In [2]: print("Sonderzeichen: \\ \" \' u\x40")
Sonderzeichen: \ " ' u@

Methoden

In der Tabelle String Methoden sind s,t und u strings, i, j und k sind Ganzzahlen. x ist eine beliebige Instanz. Die eckigen Klammern [ ] bedeuten dass dieser Eintrag optional ist.

String Methoden
Methode Wirkung
s.splitlines() Spaltet einen String in seine einzelnen Zeilen. Trennzeichen sind \n (Unix), \n\r (Win), \r (Mac).
s.split([x[,i]]) Zerteilt einen String mittels x und gibt eine Liste zurück. i begrenzt die Anzahl der Trennungen. Siehe auch rsplit.
s.find(x[, i[, j]]) Gibt den Index k des ersten Vorkommens von x im Bereich i <= k < j zurück. Gib -1 zurück wenn x nicht vorkommt.. Siehe auch rfind.
s.count(x) Gibt an, wie oft das Element x in s vorkommt.
s.replace(t, u[, i]) Ersetzt in s den String t durch String u. Mit i wird die Anzahl, wie oft t durch u ersetzt wird, begrenzt.
s.lower() Alle Buchstaben klein schreiben.
s.upper() Alle Buchstaben groß schreiben.
s.strip() Entfernt unerwünschte Zeichen auf beiden Seiten von s. Siehe auch lstrip, rstrip.
s.isalpha() True, wenn alle Zeichen in s Buchstaben sind.
s.isdigit() True, wenn alle Zeichen in s Ziffern sind.
s.islower() True, wenn alle Buchstaben in s Kleinbuchstaben sind. Siehe auch isupper, isspace.

Beispiele:

In [1]: s = "Unix\nWindows\r\nMac\rLetzte Zeile"

In [2]: s.splitlines()
Out[2]: ['Unix', 'Windows', 'Mac', 'Letzte Zeile']

In [3]: s = "Dieser String wird durchsucht"

In [4]: s.split()
Out[4]: ['Dieser', 'String', 'wird', 'durchsucht']

In [5]: s.split("e")
Out[5]: ['Di', 's', 'r String wird durchsucht']

In [6]: s.find("haha")
Out[6]: -1

In [7]: s.find("w")
Out[7]: 14

In [8]: s.count("e")
Out[8]: 2

In [9]: s.replace("wird","wurde")
Out[9]: 'Dieser String wurde durchsucht'

In [10]: s.lower()
Out[10]: 'dieser string wird durchsucht'

In [11]: s.upper()
Out[11]: 'DIESER STRING WIRD DURCHSUCHT'

In [12]: s = "    \t\n  \rUmgeben von Whitespaces   \t\t\r"

In [13]: s.strip()
Out[13]: 'Umgeben von Whitespaces'

Formatierung

Darunter versteht man die Anpassung der (Bildschirm)ausgaben auf bestimmte Art und Weise. Am besten erklärt man dies an einem Beispiel:

In [1]: h=13; m=37

In [2]: "Es ist "+str(h)+":"+str(m)+" Uhr." # klassisch, umständlich
Out[2]: 'Es ist 13:37 Uhr.'

In [3]: f"Es ist {h}:{m} Uhr."              # f-string Methode
Out[3]: 'Es ist 13:37 Uhr.'

In [4]: x = 123.4567

In [5]: f"Gleitkommazahl {x}"
Out[5]: 'Gleitkommazahl 123.4567'

In [6]: f"Gleitkommazahl {x/3:8.2f}"       # 8 Zeichen, 2 nach dem Komma
Out[6]: 'Gleitkommazahl    41.15'

Diese Methode heißt f-string (vorangestelltes f) und führt zu einer entsprechenden Auswertung von Ausdrücken, Umwandlung von Variablen und Formatierung des Ausgabestrings. Diese Methode ist ab Python 3.6 verfügbar.

Mathematische Ausdrücke innerhalb geschwungenen Klammern werden ausgewertet.

Der : innerhalb der geschwungenen Klammern ermöglicht die Ausgabe weiter zu formatieren. d.h. Wert:Laenge.Genauigkeit wobei die Laenge die gesamte Anzahl der Zeichen darstellt und die Genauigkeit die Anzahl der werttragenden Stellen.

Einige wichtige Ausgabedatentypen finden sich in Tabelle String Ausgabedatentypen.

String Ausgabedatentypen
Kennung Beschreibung
E, e Fließkommazahl im wissenschaftlichen Format (großes E oder kleines e)
f Fließkommazahl in Dezimalschreibweise
g, G Fließkommazahl in wissenschaftlicher Schreibweise, wenn Exponent kleiner als –4, sonst Dezimalschreibweise

Beispiele:

In [1]: a=0.00034545

In [2]: f"Exponential Schreibweise:{a:16E}"
Out[2]: 'Exponential Schreibweise:    3.454500E-04'  # 16 Zeichen

In [3]: #                          1234567890123456  -> 16 Zeichen

In [4]: f"Wissenschaftliche Schreibweise:{a:g}"
Out[4]: 'Wissenschaftliche Schreibweise:0.00034545'

In [5]: f"Wissenschaftliche Schreibweise:{a:12.3g}"    # 12 Zeichen, 3 werttragende Stellen
Out[5]: 'Wissenschaftliche Schreibweise:    0.000345'

In [6]: f"Wissenschaftliche Schreibweise:{a:.3g}"      # 3 werttragende Stellen
Out[6]: 'Wissenschaftliche Schreibweise:0.000345'

In [7]: f"Wissenschaftliche Schreibweise:{a/100:.3g}"  # autom. Wechsel zu 'e' Schreibweise
Out[7]: 'Wissenschaftliche Schreibweise:3.45e-06'

3.8.3. Tupel

Tupel sind:
  • lt. Python unveränderbare Sequenzen (stimmt nicht ganz ..)
  • können beliebige Datentypen enthalten
  • werden in runde Klammern gesetzt ( .. )

Beispiele:

In [1]: (2.3, 5.3, 6.2)
Out[1]: (2.3, 5.3, 6.2)

In [2]: adresse = ("Hans", "Mayer", 63)

Bemerkung

im Prinzip können Listen alles was Tupel können. Deshalb gehen wir nicht näher darauf ein.

3.9. Mengen

3.9.1. Set

Sets sind klassische Mengen aus der Mathematik: Diese:
  • kennen keine doppelten Einträge (nicht wie bei Listen),
  • werden in geschwungene Klammern gesetzt { .. },
  • erlauben Operatoren wie Durchschnitt &, Vereinigung | und Differenz -.

Beispiele:

In [1]: a = {1, 3, 3, 4}

In [2]: a
Out[2]: {1, 3, 4}

In [3]: type(a)
Out[3]: set

In [4]: b = set( [4, 6, 8] )  # Initialisierung mittels Liste

In [5]: a & b
Out[5]: {4}

In [6]: a | b
Out[6]: {1, 3, 4, 6, 8}

In [7]: a - b
Out[7]: {1, 3}

3.10. Mappings

3.10.1. Dictionary

Dictionaries sind Wörterbücher. Ein sehr mächtiges und hilfreiches Datenkonzept: Dictionaries in Python:

  • haben Einträge aus Werte-Paaren d.h. Schlüsselwort/Wert (key/value)
  • können Zahlen, Strings, etc als Schlüsselwort haben und
  • erlauben ein schnelles Suchen nach dem Schlüsselwort.
  • Auch bekannt als map (C++) oder associative array.

Beispiele:

In [1]: woerterbuch = {"Germany" : "Deutschland", "Spain" : "Spanien"}

In [2]: type(woerterbuch)
Out[2]: dict

In [3]: woerterbuch["Germany"]
Out[3]: 'Deutschland'

In [4]: for key in woerterbuch:
   ...:     print(key)
   ...:
Germany
Spain

Operatoren

In Tabelle Dictionary Operatoren ist d ein Dictionary und k der “key”.

Dictionary Operatoren
Operator Beschreibung
len(s) Liefert die Anzahl aller im Dictionary s enthaltenen Elemente.
d[k] Zugriff auf den Wert mit dem Schlüssel k
del d[k] Löschen des Schlüssels k und seines Wertes
k in d True, wenn sich der Schlüssel k in d befindet

Fortsetzung des obigen Beispiels:

In [5]: woerterbuch["French"] = "Frankreich"

In [6]: woerterbuch
Out[6]: {'Germany': 'Deutschland', 'Spain': 'Spanien', 'French': 'Frankreich'}

In [7]: len(woerterbuch)
Out[7]: 3

In [8]: del woerterbuch["Germany"]

In [9]: "Germany" in woerterbuch
Out[9]: False

Methoden

Tabelle Dictionary Methoden fasst die wichtigsten Zugriffsfunktionen zusammen.

Dictionary Methoden
Methode Beschreibung
d.clear() Löscht den Inhalt des Dictionarys d. Das Dictionary selbst bleibt bestehen.
d.copy() Erzeugt eine Kopie von d. Beachten Sie, dass nur das Dictionary selbst kopiert wird. Alle Werte bleiben Referenzen auf dieselben Instanzen.
d.items() Erzeugt eine Liste, die alle Schlüssel/Wert-Paare von d als Tupel enthält.
d.keys() Erzeugt eine Liste aller Schlüssel von d.
d.values() Erzeugt eine Liste aller Werte von d.

Fortsetzung des obigen Beispiels:

In [10]: woerterbuch
Out[10]: {'Spain': 'Spanien', 'French': 'Frankreich'}

In [11]: woerterbuch.items()
Out[11]: dict_items([('Spain', 'Spanien'), ('French', 'Frankreich')])

In [12]: woerterbuch.keys()
Out[12]: dict_keys(['Spain', 'French'])

In [13]: woerterbuch.values()
Out[13]: dict_values(['Spanien', 'Frankreich'])

In [14]: w2 = woerterbuch

In [15]: id(w2), id(woerterbuch)            # Zeiger, gleiches Woerterbuch
Out[15]: (2457905266424, 2457905266424)

In [16]: w2 = woerterbuch.copy()            # Kopie

In [17]: id(w2), id(woerterbuch)
Out[17]: (2457905783576, 2457905266424)

In [18]: id(w2['Spain'])                    # aber Values haben gleiche Id
Out[18]: 2457905543600

In [19]: id(woerterbuch['Spain'])
Out[19]: 2457905543600

In [20]: w2['Spain'] = "Irgendwas"          # bis Values veraendert werden

In [21]: w2
Out[21]: {'Spain': 'Irgendwas', 'French': 'Frankreich'}

In [22]: woerterbuch
Out[22]: {'Spain': 'Spanien', 'French': 'Frankreich'}

In [23]: id(w2['Spain'])
Out[23]: 2457905852464

In [24]: id(woerterbuch['Spain'])
Out[24]: 2457905543600

In [20]: w2.clear()

In [21]: w2
Out[21]: {}

3.11. Typumwandlungen

In bestimmten Situation besteht die Notwendigkeit den Datentyp während der Laufzeit zu wechseln.

Methoden

Tabelle Typumwandlungen Methoden fasst diese zusammen.

Typumwandlungen Methoden
Methode Beschreibung
float(x) Erzeugt aus x eine Gleitkommazahl.
int(x) Erzeugt aus x eine Ganzzahl.
str(x) Erzeugt aus x einen String.
bool(x) Erzeugt aus x einen Wahrheitswert.
dict(x) Erzeugt aus x ein Dictionary sofern x aus einer Liste von Paaren besteht
list(x) Erzeugt aus x eine Liste.

Beispiele:

In [1]: a = "123"

In [2]: float(a)
Out[2]: 123.0

In [3]: b = 435.2

In [4]: int(b)
Out[4]: 435

In [5]: bool(b)
Out[5]: True

In [6]: str(b)
Out[6]: '435.2'

In [7]: c = [(3,'drei'),(4,'vier')]

In [8]: dict(c)
Out[8]: {3: 'drei', 4: 'vier'}

In [9]: list( dict(c) )
Out[9]: [3, 4]

3.12. Übungsbeispiele

Aufgabe 3.1

Veränderbare vs. unveränderbare Datentypen:

  1. Definieren Sie eine Zahl a mit beliebigem Wert.
  2. Definieren Sie eine weitere Variable b, die auf a verweist. Überprüfen Sie ob es sich bei a und b um das selbe Objekt handelt, d.h. ob die Speicheradresse von a und b gleich ist.
  3. Addieren Sie 1 zu b. Hat sich a dadurch verändert? Hat sich die Speicheradresse von b verändert? Sind Zahlen in python daher veränderlich oder unveränderlich?
  4. Definieren Sie eine beliebige Liste liste_a.
  5. Definieren Sie eine weitere Liste liste_b, die auf liste_a verweist. Überprüfen Sie ob es sich bei liste_a und liste_b um das selbe Objekt handelt, d.h. ob die Speicheradresse von liste_a und liste_b gleich ist.
  6. Addieren Sie 1 zum ersten Element von liste_b. Verändert sich liste_a dadurch. Was ist mit den Speicheradressen? Sind Listen in python daher veränderlich oder unveränderlich?
  7. Wiederholen Sie Punkt 5) und 6) wobei liste_b jetzt als explizite Kopie von liste_a definiert wird. Was verändert sich?
  8. Definieren Sie eine beliebige Liste von Listen liste, d.h. eine Liste, die mehrere Listen enthält. Legen Sie eine explizite Kopie der liste an. Sie können überprüfen, ob eine neue Liste angelegt wurde, indem Sie z.B. 1 zum ersten Element der innersten Liste addieren und überprüfen, dass sich die ursprüngliche Liste dabei nicht verändert.

Aufgabe 3.2

Gegeben sei ein String welcher Gleitkommazahlen enthält, zum Beispiel: 4.52 ;     1.23;8.65; 1.4

  1. Extrahieren Sie die Gleitkommazahlen und fügen Sie sie in eine Liste Zahlenstrings ein.

  2. Konvertieren Sie die Elemente aus Zahlenstrings auf den Datentyp float. Fügen Sie die Zahlen in eine Liste Gleitkommazahlen ein.

  3. Berechnen Sie das Maximum der Liste und geben Sie es mit einer Nachkommastelle aus.

  4. Runden Sie die Gleitkommazahlen auf Ganzzahlen ab (z.B. 1.23 ergibt 1, 8.65 ergibt 8). Fügen Sie die Zahlen in eine Liste Ganzzahlen ein.
    • Prüfen Sie ob die Zahl 1 in der Liste vorkommt.
    • Wenn ja, wie oft und an welcher Stelle der Liste kommt sie vor?
  5. Erzeugen Sie ein Dictionary bei dem die Ganzzahl das Schlüsselwort und die Gleitkommazahl den Wert darstellt. Was passiert wenn Sie zweimal die gleiche Ganzzahl als Schlüssel verwenden?

  6. Geben Sie den Schlüssel sowie den Wert des Dictonaries im Format Schluessel=..., Wert=... in der Konsole aus.

3.13. weitere Übungsbeispiele

Aufgabe 3.3

  1. Erzeuge ein Python Skript mit beliebigem Namen mittels Spyder.
  1. Definiere darin zwei Variablen: Variable Laenge mit Wert “3” und Variable Breite mit Wert “7.43”.

  2. Berechne das Produkt beider Variablen (=Fläche) und gib es am Bildschirm mit print aus d.h. erstelle den Quellcode in Spyder und führe das Skript aus.

  3. Erzeuge eine Stringvariable Antwort mit dem Wert "Ergebnis: Flaeche =". Verbessere die vorhergehende Ausgabe indem du die Länge und Breite sowie die Fläche mit der Variable Antwort ausgibst. Beispiel Ausgabe:

    Berechnungsergebnis
    --------------------------
    Laenge            = 3
    Breite            = 7.43
    Ergebnis: Flaeche = 22.29
    
  4. Überprüfe den Datentyp, die Speicherplatznummer und den Wert aller bislang erzeugten Variablen indem du diese am Bildschirm mit print ausgibst. Versuche die Ausgabe selbsterklärend zu gestalten d.h.

    Datentypen
    --------------------------
    Laenge
      Datentyp   = <class 'int'>
      Identitaet = 14385448
      Wert       = 3
    
  5. Speichere die beiden Variablen in einer neu erzeugten Liste mit dem Namen DatenListe. Verwende dazu append. Überprüfe den Inhalt und Anzahl der Elemente welche sich in der Liste befinden z.B. mittels print.

  6. Berechne wie zuvor das Produkt beider Variablen indem du die Werte aus der Liste liest. Gibt das Ergebnis wie zuvor am Bildschirm aus. Die Ausgabe sollte selbsterklärend sein z.B.

    Liste
    --------------------------
      Inhalt  = [3, 7.43]
      Anzahl  = 2
      Flaeche = 22.29
    
  7. Speichere die beiden Variablen (Laenge und Breite) in einem neu erzeugten Dictonary DatenDict ab. Der Variablenname (Zeichenkette) dient dabei als Schlüssel.

  8. Bereche wie zuvor das Produkt beider Variablen (=Fläche) mit Hilfe der Werte aus dem Dictionary. Speichere das Ergebnis in das Dictonary DatenDict unter dem Schlüssel Flaeche ab.

  9. Erzeuge die gleiche Ausgabe wie bei der Liste mit den Ausgaben Inhalt, Anzahl, Flaeche (Ausgabe siehe oben).

  10. Überprüfe ob sich der Schlüssel Flaeche im Dictonary DatenDict befindet.

  11. Gib die Fläche aus DatenDict am Bildschirm mit 10 Digits und 3 Nachkommastellen in der Form

    Flaeche =     22.290
    

    aus.

  12. Wandle die Variable Breite in eine Ganzzahl um. Berechne damit die Fläche und gib diese aus. Warum hat sich die Fläche verändert?

Hinweis

Versuche das Skript alleine oder gemeinsam in einer Gruppe zu erstellen ohne einer Vorlage. Nur so lernt man Programmieren. Das gesamte Skript zu diesen vielen Fragen hat weniger als 50 Zeilen! Frage bei den Übungen falls etwas nicht klar ist. Unsere Erfahrung zeigt: Wer diese Aufgabe nicht selbst programmiert und die Hintergründe versteht, schafft das erste Kolloquium im Allgemeinen nicht. Beachte auch dass der folgende Stoff auf diesen Inhalten aufbaut!

Aufgabe 3.4

Volumen eines Kegels:

  1. Definieren Sie eine Liste, die 3 strings enthält: " r = 1.33", "h =  4.5" und "pi=3.1415". Hierbei ist r der Radius der Grundfläche eine Kegels, h seine Höhe und pi die mathematische Konstante π.

  2. Extrahieren Sie die Zahlenwerte aus den Strings der Liste und speichern Sie sie in den Variablen r, h und pi ab. Achten Sie darauf, dass die Strings beliebige Zahlen mit beliebig vielen Leerzeichen beinhalten können!

  3. Berechnen Sie das Volumen des Kegels und geben Sie das Ergebnis per print Befehl aus. Hinweis:

    V_{\mathrm{Kegel}} = \frac{1}{3} \cdot r^2 \cdot \pi \cdot h

  4. Erstellen Sie ein Dictionary Kegel, das die Variablen r, h und pi mit ihren jeweiligen Zahlenwerten enthält. Dabei soll der jeweilige Variablenname als string der Schlüssel sein. Für den Wert wird der jeweilige Zahlenwert als Gleitkommazahl zugeordnet.

  5. Errechnen Sie das Volumen erneut. Verwenden Sie diesmal jedoch das Dictionary Kegel für die Berechnung. Geben Sie das Ergebnis erneut per print Befehl aus.

Aufgabe 3.5

Gegeben ist eine Zeichenkette mit den Einträgen 1, zwei, 3, 4.12.

  1. Erstellen Sie eine Liste, die die durch Beistriche getrennten Elemente des Strings enthält.
  • Entfernen Sie überschüssige Leerzeichen am Ende und Anfang jedes Elements der Liste.
  • Konvertieren Sie in der Liste alle Strings, die Ganzzahlen sind zum Datentyp integer und alle Strings, die Gleitkommazahlen sind zum Datentyp float. Einträge, die keine Zahlen sind bleiben als Strings in der Liste.
  1. Überprüfen Sie ob sich 1 bzw. e in dem String bzw. der Liste befindet.
  • Welchen Datentyp muss 1 haben um in dem String bzw. der Liste gefunden zu werden?
  • Überprüfen Sie zusätzlich ob e in den Elementen der Liste enthalten ist.
  1. Geben Sie die Länge des Strings bzw. der Liste aus.
  2. Hängen Sie ein beliebiges Element an das Ende von String bzw. Liste an. Geben Sie den veränderten String / die veränderte Liste aus.
  3. Legen Sie eine Kopie des Strings / der Liste an und wiederholen Sie Punkt 4) für die Kopie. Achten sie darauf, dass sich die ursprünglichen Objekte nicht verändern!