Modularisierung

Module

Legos als Module Modulare Programmierung ist eine Seftware-Design-Technik, die auf dem allgemeinen Prinzip des modularen Designs beruht. Modulares Design ist ein Ansatz, der sich als unausweichlich und unentbehrlich schon lange vor den ersten Computern im Ingenieurwesen herausgestellt hat. Unter modularem Design versteht man, dass man ein komplexes System in kleinere selbständige Einheiten oder Komponenten zerlegt. Diese Komponenten bezeichnet man üblicherweise als Module. Ein Modul kann unabhängig vom Gesamtsystem erzeugt und separat getestet werden. In den meisten Fällen kann man ein Modul auch in anderen Systemen verwenden.

Heutzutage gibt es kaum ein Produkt, das nicht auf Modularisierung beruht, so wie Autos, Mobiltelefone, und so weiter. Computer gehören zu den Produkten, die bis zum Äußersten modularisiert sind. Das was für die Hardware ein Muss ist, stellt auch für die Software, die auf ihr läuft, eine unvermeidliche Notwendigkeit dar.

Wenn man Programme schreiben will, die lesbar, zuverlässig und und ohne hohen Aufwand wartbar sind, geht es nicht ohne modulares Software-Design, insbesondere bei größeren Software-Projekten. Es gibt verschiedene Konzepte um Programme modular zu gestalten. Der Ansatz der modularen Programmierung besteht darin, Programme systematisch in logische Teilblöcke, d.h. Module, aufzuspalten. Die Aufteilung eines Quelltextes in einzelne Teile (Module) bezeichnet man als Modularisierung.

In Python unterscheiden wir zwei Arten von Modulen:

Eine Bibliothek, egal ob aus der Standardbibliothek oder eine eigene, wird mit der import-Anweisung eingebunden.
Beispiel:
import math
Das Modul math aus der Standardbibliothek stellt mathematische Konstanten und Funktionen zur Verfügung.
Nach dem Schlüsselwort import können auch mehrere durch Komma getrennte Modulnamen folgen:
import math, random
import-Anweisungen können an jeder Stelle des Quellcodes stehen, aber man sollte sie der Übersichtlichkeit willen an den Anfang stellen.

Namensräume der Bibliotheken

Wird eine Bibliothek importiert, wie z.B.

import math
dann stehen die Namen der Bibliothek in einem eigenen Namensraum zur Verfügung.
Auf die sin()-Funktion von math kann man zunächst nur über den vollen Namen ("fully qualified") zugreifen, d.h.
math.sin(x)
Man kann auch selektiv nur einzelne Methoden/Funktionen importieren:
from math import sin, pi
Die anderen Methoden der Bibliothek stehen dann nicht zur Verfügung. Auf sin und pi kann man aber direkt (ohne math.) zugreifen.
Man kann auch eine Bibliothek komplett in den globalen Namensraum einbinden. Dabei werden dann gegebenenfalls bereits vorhande gleichlautende Namen überschrieben, wie dies im folgenden Beispiel geschieht:
>>> pi = 3.142
>>> print(pi)
3.142
>>> from math import *
>>> print(pi)
3.14159265359
>>> 

Umbenennen des Namensraumes beim Import

Beim Import einer Bibliothek kann man auch einen neuen Namen für den Namensraum wählen:

>>> import math as mathematik
>>> print(mathematik.cos(mathematik.pi))
-1.0
Ein Namensraum math existiert in obigem Beispiel nicht, sondern nur ein Namensraum mathematik.
Im folgenden Beispiel werden einzelne Methoden des math-Moduls umbenannt, so werden pow() in power() und sin() in sinus() umbenannt:
>>> from math import pi,pow as power, sin as sinus
>>> power(2,3)
8.0
>>> sinus(pi)
1.2246467991473532e-16

Modul-Arten

Es gibt verschiedene Modul-Arten:

Suchpfad für Module

Wenn man ein Modul z.B. abc importiert, sucht der Interpretor nach abc.py in der folgenden Reihenfolge:

  1. Im aktuellen Verzeichnis
  2. PYTHONPATH
  3. Falls PYTHONPATH nicht gesetzt ist, wird installationsabhängig im Default-Pfad gesucht, also unter Linux/Unix z.B. in /usr/lib/python2.5.
>>> import math >>> math.__file__ '/usr/lib/python2.5/lib-dynload/math.so' >>> import random >>> random.__file__ '/usr/lib/python2.5/random.pyc'

Inhalt eines Moduls

Mit der build-in-Funktion dir() kann man sich die in einem Modul definierten Namen ausgeben lassen.

>>> dir(math)
['__doc__', '__file__', '__name__', 'acos', 'asin',
'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 
'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot',
'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 
'sin', 'sinh', 'sqrt', 'tan', 'tanh']
>>> 
Ohne Argumente liefert dir() die definierten Namen
>>> import math
>>> col = ["red","green","blue"]
>>> dir()
['__builtins__', '__doc__', '__name__', 'col', 'math']

Eigene Module

Die beiden folgenden Funktionen fib(), die den n-ten Fibonacci-Wert zurückliefert, und die Funktion fiblist() werden in einer Datei fibonacci.py gespeichert.

def fib(n):
    a, b = 0, 1
    for i in range(n):
        a, b = b, a + b
    return a

def fiblist(n):
    fib = [0,1]
    for i in range(1,n):
        fib += [fib[-1]+fib[-2]]
    return fib
Von einem anderen Programm oder von der interaktiven Shell kann man nun, falls fibonacci.py innerhalb des Suchpfades zu finden ist, die Datei mit den beiden Fibonacci-Funktionen als Modul aufrufen.
>>> import fibonacci
>>> fibonacci.fib(10)
55
>>> fibonacci.fiblist(10)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>>> fibonacci.__name__
'fibonacci'
>>> 

Eigene Module

Python ermöglicht es, dass man mehrere Module in einem Paket kapseln kann. Ein Paket kann beliebig viele weitere Pakete enthalten.

Um ein Paket zu erstellen, muss im Wesentlichen ein Unterordner erzeugt werden. In diesem Ordner muss dann eine Datei mit dem Namen __init__.py existieren.

Die Datei kann leer sein oder Initiali- sierungscode ent- halten, der beim Einbindenbinden des Paketes einmalig ausgeführt wird.