Modularisierung
Die Modularisierung von Quellcode ermöglicht es Funktionen oder Klassen an unterschiedlichen Stellen eines Programms wiederzuverwenden. Darüberhinaus können Funktionen oder Klassen im Kontext von Paketen sogar in andere Programme integriert werden oder aus anderen Programmen geladen werden.
Der Begriff Modul ist in der Softwareentwicklung nicht einheitlich definiert. Generell steht der Begriff für eine eigenständige Komponente innerhalb eines größeren Programms. Im Kontext von Python ist der Begriff Modul konkret definiert. Ein Modul entspricht dabei dem Inhalt einer Python Datei. Kurz gesagt eine .py Datei
ist ein Modul
in Python.
Beispiel: Modularisierung
Es wurde die Datei distance_functions.py
erzeugt, welche unterschiedliche Implementierung von gängigen Distanzfunktionen enthält. Als Beispiel die Euklidische- und die Manhatten Distanz:
# Inhalt der Datei distance_functions.py
def euclidean_distance(point1=[], point2=[]):
return sum((p - q) ** 2 for p, q in zip(point1, point2)) ** 0.5
def manhatten_distance(point1=[], point2=[]):
return sum(abs(p - q) for p, q in zip(point1, point2))
# weitere Implementierungen ...
Innerhalb einer zweiten Datei main.py
, welche im selben Ordner liegt, können die Funktionen der Datei distance_functions.py
importiert werden. Der Dateiname definiert damit auch den Modulname distance_functions
. Mit dem Schlüsselwort import
wird der Import des Moduls durchgeführt. Auf die Inhalte eines Moduls kann mit dem Dot-Operator
zugegriffen werden.
# Inhalt der Datei main.py
import distance_functions
dist = distance_functions.euclidean_distance([1, 2], [3, 4])
print(dist) # 2.828427...
Import Syntax
Python definiert unterschiedliche Schreibweisen um Inhalte eines Moduls zu importieren. Wichtig dabei sind die Schlüsselwörter import
, from
und as
.
Die Default Schreibweise wäre die ausschließliche Nutzung des import
Schlüsselwortes:
import distance_functions
distance_functions.euclidean_distance([1, 2], [3, 4])
Alias für Namensraum mit as
Mit dem Schlüsselwort as
kann ein Alias für den Modulnamen vergeben werden. Der Vorteil des Alias ist, dass der lange Modulname distance_functions
gekürzt werden kann:
import distance_functions as df
df.euclidean_distance([1, 2], [3, 4])
Das Modul distance_functions
wird im importierenden Modul unter dem Bezeichner df
bekannt gemacht. df
ist der definierte Alias vom vollständigen Modulnamen distance_functions
.
Ausgewählte Bestandteile mit from
importieren
Mit dem Schlüsselwort from
können ausgewählte Bestandteile des Moduls in den aktuellen Namensraum bzw. in das aktuelle Modul importiert werden.
from distance_functions import euclidean_distance, manhattan_distance
euclidean_distance([1, 2], [3, 4])
manhattan_distance([1, 2], [3, 4])
Aus dem Modul distance_functions
werden explizit nur die Funktionen euclidean_distance
und manhatten_distance
importiert. Diese können somit auch ohne Modul-Prefix (zB distance_functions.euclidean_distance
) verwendet werden.
Namenskonflikte
Bei dieser Art des Import kann es zu Namenskonflikten kommen. Beispielsweise könnte dies passieren, wenn im importierenden Modul bereits eine Funktion euclidean_distance
definiert wird.
Alles mit *
importieren
Durch die Angabe eines *
können alle Bestandteile eines Modules in den aktuellen Namensraum importiert werden. Der *
sollte nur verwendet werden, wenn die Bestandteile des Moduls bekannt sind und wirklich alle geladen werden sollen. Ebenfalls sollte man mögliche Namenskonflikte bedenken.
from distance_functions import *
Alias für Importe mit as
Mit dem Schlüsselwort as
kann auch eine Funktion oder Klasse die importiert werden soll mit einem Alias definiert werden:
from distance_functions import euclidean_distance as ed
ed([1, 2], [3, 4])
Python Standardbibliothek
Mit Installation von Python wird auch die Python Standardbibliothek mitgeliefert. Darin befindet sich eine Menge von nützlichen Modulen, welche innerhalb eigener Programme importiert werden können.
Eine vollständige Übersicht über alle Module der Standardbibliothek findet sich in der Python Dokumentation. Im folgenden soll exemplarisch, anhand des random
Moduls, gezeigt werden wie Module der Standardbibliothek genutzt werden können.
random
Modul
Das random
Modul stellt nützliche Funktionen bereit um Zufallszahlen zu erzeugen.
Im folgenden Beispiel wird das Modul random
importiert und mit den zwei Funktionen random
bzw. randint
werden Zufallszahlen erzeugt. Das Modul bietet eine Vielzahl weiterer Funktionen, welche über die Dokumentation beschrieben werden.
import random
print(random.random()) # float Zufallszahl zwischen 0 und 1
print(random.randint(0, 9)) # int Zufallszahl zwischen 0 und 9
Random Seed
Ein Generator von Zufallszahlen benötigt einen Seed. Anhand dieses Seed werden Zufallszahlen sequenziell errechnet. Als Defaultwert wird der Seed gerne über den aktuellen Timestamp initialisiert. Um einen Zufallszahlengenerator deterministischer zu machen und zB Replizierbarkeit für ein Notebook herzustellen, kann ein Seed explizit gesetzt werden.
import random
random.seed(99)
print(random.random()) # 0.40397807494366633
print(random.random()) # 0.20007544457494542
print(random.random()) # 0.17880232058661227
Durch das setzen des beliebigen Seeds 99
würde auch das mehrmalige Ausführen des Programms immer dieselben Zufallszahlen generieren.
Python Package
Um Module in eine größere Einheit zusammen zu fassen können Packages erzeugt werden. Ein Python Package ist dabei "einfach gesprochen" ein Ordner im Dateisystem, welcher eine Datei __init__.py
enthält.
Tiefergehendes Verständnis für Python Packages ist vor allem wichtig, wenn man eigene Bibliotheken entwickeln möchte. Dies würde den Rahmen der LV sprengen, deshalb wird hier auf weiterführende Dokumentation verwiesen.
Freie (unter FOSS Lizenzen verteilt) Python Packages können als Bibliotheken über einen Paketmanager (zb pip
) integriert werden. Im Python Package Index finden sich alle freien Python Packages.