15.1. Dynamische und statische Typisierung#

Für statisch getypten Sprache wird der Datentyp von Werten und Variablen geprüft bevor der Programmcode ausgeführt wird. Im Gegenteil dazu wird diese Prüfung für dynamisch getypte Sprachen erst zur Laufzeit durchgeführt, also während der Code ausgeführt wird.

Damit Sie sich unter einer statisch getypten Sprache auch etwas vorstellen können folgt ein Java-Programmcode, welcher die Summe aller Quadratzahlen von 1 bis n berechnet und ausgibt:

public class Main {

    public static void main(String args[]) {
        int n = Integer.parseInt(args[0]);
        int sum = 0;

        for (int i = 1; i < n; i++) {
            sum += i * i;
        }

        System.out.println("Sum squares from 1 to " + n + " = " + sum);
    }
}

Um den Code auch tatsächlich auszuführen, muss er in einer Datei namens Main.java stehen. Wir müssen den Java-Compiler befehligen, diese Datei zu übersetzten. Dies geht über die Kommandozeile über den Befehl javac Main.java. Der Compiler erzeugt eine Datei mit dem Namen Main.class. Um das Programm auszuführen starten wir es schließlich mit java Main 10, wobei 10 das 0-te Argument des Programms ist.

Exercise 15.1 (Datentypen erraten)

Geben Sie an von welchem Datentyp die Variablen n, sum, i, und args im obigen Java-Programm sind.

Führen Sie folgenden Code aus:

number = 5
number = number + 5
print(number)
number = number + 'b'
10
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[1], line 4
      2 number = number + 5
      3 print(number)
----> 4 number = number + 'b'

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

Dieser führt zu einem bekannten Fehler: unsupported operand type(s) for +: 'int' and 'str' und dennoch wird die ganze Zahl number ausgegeben. In anderen Worten der Code läuft solange bis es kracht.

Lassen Sie uns das ganze einmal in Java transformieren:

int number = 5;
number = number + 5;
System.out.println(number);
number = number + "b";

Dieser Code wird gar nicht erst ausgeführt werden. Stattdessen erhalten wir eine ähnliche Fehlermeldung vor der Ausführung. In der ersten Zeilen sehen wir jedoch auch, dass wir den Datentyp für number explizit definieren müssen! In Java ist der Datentyp einer Variablen (hier number) auf festgelegt solange die Variable existiert. Auch folgender Code führt zu einem Fehler:

int number = 5;
number = "b";

und auch dieser hier:

int number = 5;
String number = "b";

Dadurch dass Typen während der Ausführung gar nicht mehr vorhanden sind, gelten für die Typisierung strengere Regeln. Andernfalls wäre dies nicht möglich.

Im Gegensatz dazu können wir in Python viel ‚freier‘ mit Typen hantieren. Der Äquivalente Code wird einwandfrei ausgeführt:

number = 5
number = 'b'
number = 5
number = 'b'

15.1.1. Was ist besser?#

Die einfache Antwort hierauf lautet: nichts von beidem. Am liebsten hätte man natürlich eine dynamische Typisierung bei der dennoch die Typen auf Korrektheit vor dem Programmlauf überprüft werden.

Die explizite Angabe des Datentyps bei statisch getypten Sprachen dient der Dokumentation und macht den Code oft lesbarer ohne zusätzliche Kommentare hinzuzufügen – der Code ist die Dokumentation.

Auf der anderen Seite hat eine statische Typisierung weitreichende Auswirkungen auf die Struktur des Codes. Wir können auf diese nicht im Detail eingehen, doch erfordern statisch getypte Sprachen einen viel strikteren Umgang mit Typen und deren Definition. Konzepte wie Vererbung und Polymorphie werden unerlässlich.

Im allgemeinen sind statisch getypte Sprachen hungriger, was die Anzahl der Zeichen des geschriebenen Codes angeht. Mit dynamisch getypte Sprachen erreicht man oft den gleichen Effekt mit deutlich weniger Zeilen Code.

In der Kategorie der Laufzeit des Codes gewinnen statisch getypte Sprachen. Vor der Ausführung sind alle Typen aller Werte, Variablen usw. bekannt. Somit können Sie sich vorstellen, dass Übersetzer / Compiler den Code besser optimieren können. Zum Beispiel kann die Typinformation während der Ausführung des Codes vergessen werden – das spart Speicherplatz.

15.1.2. Sowohl als auch?#

Python ist dynamisch getypt. Jedoch ruft Python intern C/C++ Code auf und dieser ist statisch getypt! Wir sind zwar noch immer nicht am Optimum: Typisierungstests vor der Laufzeit und dynamische Typen, aber wir sind nah dran. Python ist immer dann schnell, wenn der statisch getypte Code aufgerufen wird und immer dann langsam wenn wir lange im Python-Code selbst (der dynamisch getypt ist) verweilen.

15.1.3. Typ hints mit Python#

Mit Python 3.6 wurde eine Syntax eingeführt mit der wir den Datentyp trotz dynamischer Typisierung direkt im Code angeben können. Wir werden dies im Kurs nicht verwenden, wollen es Ihnen aber auch nicht vorenthalten. Der angegebene Typ dient der reinen Dokumentation und hat keinerlei Auswirkungen auf die Laufzeit. Manche Entwicklungsumgebungen wie Visual Studio Code (SVCode) unterstützen auf Grundlage dieser Typ hints Warnmeldungen bzw. Fehlermeldungen.

Mit Type hints wird aus

number = 5
number = 'b'

folgender Code

number : int = 5
number : str = 'b'

Dieser wird ausgeführt wie zuvor doch Ihre Entwicklungsumgebung wird Sie vermutlich warnen, dass hier der Typ gewechselt wird. Besonders für Funktionen ist dies hilfreich, um die Dokumentation direkt in den Code zu integrieren. Zum Beispiel wird aus

def add(x, y):
    return x + y

folgender Code

def add(x: int, y: int) -> int:
    return x + y

Wir geben uns und dem- oder derjenigen, welche unseren Code benutzt zu verstehen, dass die Funktion zwei ganze Zahlen erwartet und eine ganze Zahl zurückliefert.