20 Modularisierung
Unter Modularisierung versteht man die Aufteilung des Quelltextes in sogenannte Module. Ein Modul stellt üblicherweise Datentypen und Funktionen bereit, die einem bestimmten Zweck dienen, beispielsweise der Arbeit mit Dateien eines bestimmten Dateiformats. Module können in einem Programm eingebunden werden und stellen dem Programmierer dann die enthaltene Funktionalität zur Verfügung. Grundsätzlich gibt es zwei Arten von Modulen:
- Zum einen kann jedes Python-Programm globale Module, auch Bibliotheken genannt, einbinden. Globale Module werden systemweit installiert und stehen allen Python-Programmen gleichermaßen zur Verfügung. Es ist möglich, eigene globale Module zu schreiben oder ein globales Modul eines Drittanbieters zu installieren.
- Die zweite Möglichkeit zur Modularisierung sind lokale Module. Darunter versteht man die Kapselung einzelner Programmteile in eigene Programmdateien. Diese Dateien können wie Bibliotheken eingebunden werden, sind aber in keinem anderen Python-Programm verfügbar. Diese Form der Modularisierung hilft bei der Programmierung, da sie dem Programmierer die Möglichkeit gibt, langen Programm-Code überschaubar auf verschiedene Programmdateien aufzuteilen.
In Python besteht der einzige Unterschied zwischen lokalen und globalen Modulen darin, wo sie gespeichert sind. Während sich lokale Module in der Regel im Programmverzeichnis bzw. in einem seiner Unterverzeichnisse befinden, sind globale Module in einigen festgelegten Verzeichnissen der Python-Installation gespeichert.[ 80 ](Selbst geschriebene Bibliotheken können Sie in das Unterverzeichnis site-packages der Python-Installation speichern. Dort werden üblicherweise auch Bibliotheken von Drittanbietern installiert. )
20.1 Einbinden globaler Module
Ein globales Modul, sei es ein Teil der Standardbibliothek oder ein selbst geschriebenes, kann mithilfe der import-Anweisung eingebunden werden. Wir werden in den Beispielen hauptsächlich das Modul math der Standardbibliothek verwenden. Das ist ein Modul, das mathematische Funktionen wie sin oder cos sowie mathematische Konstanten wie pi bereitstellt. Um sich diese Funktionalität in einem Programm zunutze machen zu können, wird die import-Anweisung in der folgenden Form verwendet:
>>> import math
Eine import-Anweisung besteht aus dem Schlüsselwort import, gefolgt von einem Modulnamen. Es können mehrere Module gleichzeitig eingebunden werden, indem sie, durch Kommata getrennt, hinter das Schlüsselwort geschrieben werden:
>>> import math, random
Dies ist äquivalent zu:[ 81 ](Aus Gründen der Übersicht wird generell empfohlen, jedes Modul in einer separaten Zeile zu importieren. )
>>> import math
>>> import random
Obwohl eine import-Anweisung prinzipiell überall im Quellcode stehen kann, ist es der Übersichtlichkeit halber sinnvoll, alle Module zu Beginn des Quelltextes einzubinden.
Nachdem ein Modul eingebunden wurde, wird ein neuer Namensraum mit seinem Namen erstellt. Über diesen Namensraum sind alle Funktionen, Datentypen und Werte des Moduls im Programm nutzbar. Mit einem Namensraum kann wie mit einer Instanz umgegangen werden, und die Funktionen des Moduls können wie Methoden des Namensraums verwendet werden. So bindet folgendes Beispielprogramm das Modul math ein und berechnet den Sinus der Kreiszahl π:
>>> import math
>>> math.sin(math.pi)
1.2246467991473532e-16
Es ist möglich, den Namen des Namensraums durch eine import/as-Anweisung festzulegen:
>>> import math as mathematik
>>> mathematik.sin(mathematik.pi)
1.2246467991473532e-16
Dieser neue Name ist keine zusätzliche Option. Das Modul math ist nun ausschließlich über den Namensraum mathematik erreichbar.
Darüber hinaus kann die import-Anweisung so verwendet werden, dass kein eigener Namensraum für das eingebundene Modul erzeugt wird, sondern alle Elemente des Moduls in den globalen Namensraum des Programms eingebunden werden:
>>> from math import *
>>> sin(pi)
1.2246467991473532e-16
Wenn die import-Anweisung in dieser Weise verwendet wird, sollten Sie beachten, dass keine Referenzen oder Funktionen des einzubindenden Moduls in den aktuellen Namensraum importiert werden, wenn sie mit einem Unterstrich beginnen. Diese Elemente eines Moduls werden als privat und damit als modulintern angesehen.
[»] Hinweis
Der Sinn von Namensräumen ist es, thematisch abgegrenzte Bereiche, also zum Beispiel den Inhalt eines Moduls, zu kapseln und über einen gemeinsamen Namen anzusprechen. Wenn Sie den kompletten Inhalt eines Moduls in den globalen Namensraum eines Programms einbinden, kann es vorkommen, dass die Bibliothek mit eventuell vorhandenen Referenzen interferiert. In einem solchen Fall werden die bereits bestehenden Referenzen kommentarlos überschrieben, wie das folgende Beispiel zeigt:
>>> pi = 1234
>>> from math import *
>>> pi
3.141592653589793
Aus diesem Grund ist es sinnvoll, ein Modul, wenn es vollständig eingebunden wird, in einem eigenen Namensraum zu kapseln und damit die Anzahl der im globalen Namensraum eingebundenen Elemente möglichst gering zu halten.
Im Hinweiskasten wurde gesagt, dass man die Anzahl der in den globalen Namensraum importierten Objekte möglichst gering halten sollte. Aus diesem Grund ist die oben beschriebene Form der from/import-Anweisung nicht praktikabel. Es ist aber möglich, anstelle des Sterns eine Liste von zu importierenden Elementen des Moduls anzugeben:
>>> from math import sin, pi
>>> sin(pi)
1.2246467991473532e-16
In diesem Fall werden ausschließlich die Funktion sin und die Konstante pi in den globalen Namensraum importiert. Auch hier ist es möglich, durch ein dem Namen nachgestelltes as einen eigenen Namen festzulegen:
>>> from math import sin as hallo, pi as welt
>>> hallo(welt)
1.2246467991473532e-16
So viel zum Einbinden globaler Module. Sie werden die Standardbibliothek von Python im dritten Teil dieses Buchs noch ausführlich kennenlernen.
[»] Hinweis
Die Aufzählung der mit einer from/import-Anweisung zu importierenden Objekte kann unter Umständen recht lang werden. In solchen Fällen darf sie in runde Klammern gefasst werden. Der Vorteil dieser Schreibweise ist, dass eingeklammerte Ausdrücke beliebig formatiert, unter anderem auch auf mehrere Zeilen umbrochen werden dürfen:
>>> from math import (sin, cos, tan,
... sinh, cosh, tanh)
Beachten Sie, dass die einzubindenden Module bei einer normalen import-Anweisung nicht in Klammern gesetzt werden dürfen.