Home | Lehre | Videos | Texte | Vorträge | Software | Person | Impressum, Datenschutzerklärung | Blog RSS

Stand: 2024-07-04
weitgehend formuliert von Claude 3.5 Sonnet

Module und Packages

Konzept der Modularisierung

Der Hauptzweck der Modularisierung ist es, komplexe Systeme in kleinere, überschaubare und wiederverwendbare Teile zu zerlegen. Dies bringt mehrere wichtige Vorteile mit sich:

  1. Übersichtlichkeit und Wartbarkeit. Große Programme werden in kleinere, leichter verständliche Einheiten aufgeteilt. Dies macht den Code einfacher zu lesen, zu verstehen und zu warten. Änderungen können oft in einzelnen Modulen vorgenommen werden, ohne das gesamte System zu beeinflussen.

  2. Wiederverwendbarkeit. Gut gestaltete Module können in verschiedenen Projekten wiederverwendet werden. Dies spart Zeit und sorgt dafür, dass der Code öfter angewendet und damit getestet wird.

  3. Arbeitsteilung und Zusammenarbeit. Verschiedene Entwickler oder Teams können gleichzeitig an unterschiedlichen Modulen arbeiten. Dies ermöglicht eine effizientere Entwicklung, besonders bei größeren Projekten.

  4. Trennung von Zuständigkeiten. Jedes Modul kann sich auf eine spezifische Aufgabe oder Funktionalität konzentrieren. Dies fördert eine klare Struktur und erleichtert das Debuggen.

  5. Abstraktion und Kapselung. Module können komplexe Funktionalitäten hinter einfachen Schnittstellen verbergen. Benutzer eines Moduls müssen nicht die internen Details verstehen, um es zu verwenden.

  6. Skalierbarkeit. Modulare Systeme sind leichter zu erweitern und zu skalieren. Neue Funktionen können oft durch Hinzufügen neuer Module implementiert werden, ohne bestehenden Code stark zu verändern.

  7. Testbarkeit. Einzelne Module können unabhängig voneinander getestet werden. Dies erleichtert das Schreiben von Tests und das Finden von Fehlern.

  8. Flexibilität und Anpassbarkeit. Module können ausgetauscht oder aktualisiert werden, ohne das gesamte System neu zu schreiben. Dies ermöglicht eine einfachere Anpassung an sich ändernde Anforderungen.

Ein Alltagsbeispiel zur Veranschaulichung: Stellen Sie sich ein modernes Auto vor. Es besteht aus vielen Modulen (Motor, Getriebe, Klimaanlage, Infotainmentsystem etc.). Jedes dieser Module - kann unabhängig entwickelt und getestet werden, - kann bei Bedarf repariert oder ausgetauscht werden, ohne das ganze Auto neu zu bauen, - ermöglicht verschiedene Konfigurationen (z.B. verschiedene Motoren in der gleichen Karosserie).

In der Softwareentwicklung funktioniert die Modularisierung ähnlich. Sie erlaubt es, komplexe Systeme zu erstellen, die dennoch flexibel, wartbar und erweiterbar bleiben. Gleichzeitig macht die Modularisierung die Softwareentwicklung effizienter, flexibler und nachhaltiger, besonders bei größeren und komplexeren Projekten.

Module in Python

In Python sind Module ganz normale .py-Dateien. Angenommen, wir haben ein Modul namens mathe_helfer.py mit folgendem Inhalt:

def addiere(a, b):
    return a + b

def multipliziere(a, b):
    return a * b

Alle Elemente (also Variablen, Funktionen, Klassen) eines solchen Moduls können in anderen Python-Dateien verwendet werden – und damit auch in anderen Modulen verwendet werden.

Import von Modulen

In einem anderen Programm können wir dieses Modul nun so verwenden:

import mathe_helfer

ergebnis1 = mathe_helfer.addiere(5, 3)
ergebnis2 = mathe_helfer.multipliziere(4, 2)
print(ergebnis1)  # Ausgabe: 8
print(ergebnis2)  # Ausgabe: 8

In dem Programm, das das Modul verwendet, muss man immer mathe_helfer vor die Namen der verwendeten Elemente schreiben. Das ist zwar übersichtlich, kann aber nerven.

Knapper ist der Import mit einem Alias, hier mh:

import mathe_helfer as mh

ergebnis1 = mh.addiere(5, 3)
ergebnis2 = mh.multipliziere(4, 2)
print(ergebnis1)  # Ausgabe: 8
print(ergebnis2)  # Ausgabe: 8
print(mh.PI)  # Ausgabe: 3.14159

Wenn man nur ausgewählte Elemente aus dem Modul benötigt, kann man diese gezielt importieren und dann ohne Namenszusätze verwenden. Das kann allerdings zu Namenskollisionen führen, zum Beispiel, wenn man in der folgenden Beispieldatei noch eine eigene Funktion addiere haben wollen würde:

from mathe_helfer import addiere, multipliziere

ergebnis1 = addiere(5, 3)
ergebnis2 = multipliziere(4, 2)
print(ergebnis1)  # Ausgabe: 8
print(ergebnis2)  # Ausgabe: 8

Es ist zwar bequem, aber wegen der Gefahr von Namenskollisionen keine gute Idee, einfach mit * alle Elemente eines Moduls (außer denen, deren Name mit einem Unterstrich anfängt) zu importieren:

from mathe_helfer import *

ergebnis1 = addiere(5, 3)
ergebnis2 = multipliziere(4, 2)
print(ergebnis1)  # Ausgabe: 8
print(ergebnis2)  # Ausgabe: 8

Im Prinzip kann ein import statt am Anfang einer Python-Datei auch mitten im Programm stehen, sogar innerhalb eines if. Aber Vorsicht damit!

Packages in Python

Solche Bibliotheken wie Matplotlib und PySide wären für ein einziges Modul, das ja nur aus einer Datei besteht, viel zu komplex. Deshalb gibt es in Python noch eine höhere Ebene der Modularisierung, nämlich Packages. Der Import von Packages sieht äußerlich aus wie der oben beschriebene Import von Modulen.

Ein Package ist ein Verzeichnis, das mehrere Module enthält. Es sollte eine spezielle Datei namens __init__.py enthalten. Packages können auch Unter-Packages enthalten, was eine hierarchische Strukturierung ermöglicht.

Die Datei __init__.py wird beim Import des Packages ausgeführt, so dass dort allgemeine Vorbereitungen getroffen werden können. Ebenfalls kann zum Beispiel in jener Datei festgelegt werden, welche Elemente mit dem (nicht empfohlenen!) from ... import * importiert werden und welche nicht.