6. Modularisierung

Darunter versteht man die Aufteilung des Quelltextes in einzelne Teile, sogenannte Module.

Es gibt 2 Möglichkeiten:

  • Das Einbinden von Bibliotheken (engl. Libraries) oder
  • die Modularisierung eigener Programmteile (Funktionen, Klassen) durch Aufteilung in eigene Dateien um sehr langen Programmcode überschaubar zu machen. Diese Dateien können wie Bibliotheken eingebunden werden

Es ist möglich sowohl eigene Bibliotheken, die Python Standardbibliothek oder Bibliotheken eines Drittanbieters einzubinden.

6.1. Einbinden externer Programmbibliotheken

Je nach verwendeter Python Version, müssen eventuell vorab Bibliotheken installiert werden.

Danach können diese mit einer import Anweisung eingefügt und verwendet werden:

In [1]: import math

In [2]: print(math.sin(math.pi))
1.2246467991473532e-16

Der Zusatz math vor sin zeigt an, welche sin() Funktion verwendet werden soll (jene aus dem Modul bzw. Namensraum math).

Mit globals() nach dem import sieht man was passiert!

In [3]: globals()
Out[3]:
{'__name__': '__main__',
 ...
 '_i1': 'import math',
 'math': <module 'math' (built-in)>,
 '_i2': 'print(math.sin(math.pi))',
 '_i3': 'globals()'}

Bei langen bzw. oft verwendeten Namen schreibt man:

import numpy as np
np.array([1,2,3])

Hinweis

Verwenden Sie nicht die Anweisung:

from math import *

um Überraschungen zu vermeiden. Es werden dadurch alle Funktionen in den Namensraum geladen. Anbei ein Beispiel:

In [1]: pi = 1234               # meine definierte Variable pi

In [2]: pi
Out[2]: 1234

In [3]: from math import *      # importiere Modul, darin gibt es auch pi!

In [4]: pi                      # mein altes pi wurde ueberschrieben
Out[4]: 3.141592653589793

Beachte dass die Variable pi durch den Import überschrieben wurde ohne aufzufallen.

6.1.1. Einige interessante Python Module:

Eine Liste der Pakete, die für Ihre Anaconda-Installation verfügbar sind finden Sie unter folgendem Link: Packages

Einige interessante Pakete sind (Details später) z.B.:
  • math: Mathemtische Funktionen wie cos, sin, exp, etc. und mathematische Konstanten wie pi, e, etc.
  • numpy: Package zum einfachen Arbeiten mit Vektoren und Matrizen, linearer Algebra, etc.
  • matplotlib: Plotten und Illustrieren von 2- und 3-dimensionalen Daten.
  • scipy: Mathematische Operationen wie Integrieren von Funktionen, Interpolieren von Datenpunkten, Optimierung, etc.
  • openpyxl: Schreiben und Lesen von Excel-Files mittels python.

6.2. Eigene Module

Die Verwendung eines eigenen Moduls ist sehr einfach und besteht aus 2 Schritten:

  1. Erstellung des Moduls = Python Skript z.B. modul_name.py mit Funktionen, Klassen, etc.

  2. Einbinden des obigen Files in ein Hauptprogrammes z.B. programm.py mit:

    import meinModul
    

Im folgenden ein Beispiel eines Mathematik Moduls. Zunächst wird ein Modulfile dpMath.py mit folgenden Inhalt erzeugt:

"""
File    : dpMath.py
Author  : D.H. Pahr 
Date    : 25.06.2020

Mathematik Modul
"""

# Funktion 
def fak(zahl): 
   ergebnis = 1 
   for i in range(2, zahl+1): 
      ergebnis *= i 
   return ergebnis 

Hinweis

Ein Tipp zur Namensgebung des Files mit dem Modul:

  • Initialen des Erstellers, Projektes, etc hier dp gefolgt von
  • markantem Namen der den Inhalt beschreibt (Math).

Als zweiter Schritt wird das Hauptprogramm erstellt z.B. modul_demo.py, indem das Modul geladen wird:

import dpMath

# Hauptprogramm
eingabe = 5 
ergebnis = dpMath.fak(eingabe)  # Funktionsaufruf aus dpMath
print(ergebnis)

Aber: Woher weiss Python, wo dpMath.py ist? Dazu sollte man wissen:

  • Python sucht zunächst in dem Verzeichnis in welchem modul_demo.py gestartet wurde.
  • Findet es dort dpMath.py nicht, sucht es an Stellen des SystempfadesPYTHONPATH”.

Eventuell muss dieser von Hand gesetzt werden (siehe dazu WWW).

Abschließend noch ein Beispiel wie man beides (Modul und Modultest) kombinieren kann. Dazu erzeugt man ein Pythonskript mit 2 Teilen:

# Teil 1: Wird bei 'import' Anweisung importiert,
#         beim Skriptaufruf NICHT ausgefuehrt.
def meineFunktion():
    # Es folgt die Implementierung ...
    print("Funktion meineFunktion() wurde aufgerufen!")

# Teil 2: Wird bei 'import' Anweisung NICHT importiert,
#         beim Skript Aufruf ausgeuehrt.
if __name__ == '__main__' :
    # Hier stehen z.B. Funktionstests.
    meineFunktion()

6.3. Pakete

Mehrere Module kann man in einem sogenannten Paket zusammenfassen bzw. kapseln. Zum Beispiel effekte.blur verweist auf ein Untermodul blur im Paket effekte (siehe Abbildung Beispiel einer Paketstruktur).

_images/packet.png

Beispiel einer Paketstruktur

So wie Module davor bewahren sich Sorgen um andere (gleichlautende) globale Variablennamen zu machen (siehe Beispiel mit pi oben), bewahren Pakete davor sich Sorgen um andere Modulnahmen zu machen.

6.4. Übungsbeispiele

Aufgabe 6.1

Verändern Sie Ihre Lösung zu Aufgabe 5.1, sodass die Funktion berechne_Distanz nicht im selben Skript definiert wird, sondern importiert wird. Welche verschiedene Arten gibt es das zu tun?

6.5. weitere Übungsbeispiele

Aufgabe 6.2

Ausgangspunkt ist das Pythonskript aus Aufgabe 5.3 mit der Funktion Negiere(A), welches mit Vektoren und Matrizen operiert.

  1. Importieren Sie das File als Modul in ein leeres Python Skript.
  2. Testen Sie die Funktion mit entsprechen Vektoren und Matrizen mittels print Ausgaben.
  3. Importieren Sie das Paket numpy mittels import numpy.
  4. Definieren Sie ensprechende Vektoren und Matrizen mit numpy.array(..). Verwenden Sie die gleichen Werte wie unter Punkt 2.
  5. Testen Sie das Negieren (einfach mittels -) und vergleichen Sie das Ergebnis mit dem durch die Funkition Negiere(..).