Zum Inhalt springen

Ing Mathematik: Python

Aus Wikibooks


Hallo Welt und allgemeine Hinweise

[Bearbeiten]

Was ist Python

[Bearbeiten]
  • Python ist eine universelle höhere Programmiersprache.
  • Python ist objektorientiert.
  • Python ist Open-Source (Python Software Foundation License).
  • Python ist für viele Betriebssysteme erhältlich (z.B. für Linux, MS Windows, macOS).
  • Python ist ein Interpreter.
  • Python ist durch Module fast beliebig erweiterbar.
  • Python als Programmiersprache ist case-sensitive - d.h. Groß- und Kleinschreibung ist relevant bei der Eingabe von Befehlen.
  • Python ist in etlichen Anwendungsprogrammen (z.B.  FreeCAD,  LibreOffice,  GIMP,   Blender) als Makrosprache verwendbar.
Wikipedia hat einen Artikel zum Thema:


Python installieren

[Bearbeiten]

MS Windows

[Bearbeiten]

Laden Sie das aktuelle Python-Paket von der Webseite [1] herunter. Weiter geht es wie bei jedem anderen größeren zu installierenden Programm. Einfach das Installationsprogramm im Explorer doppelklicken und den Anweisungen des Setup-Programmes folgen.

Linux

[Bearbeiten]

Entweder ist Python bereits standardmäßig installiert, ansonsten ist die Installation mittels Paketmanagementsystem einfach möglich. Aber auch die Spyder-Entwicklungsumgebung ([2]) bietet einen guten Einstieg mit Python (das gilt auch für MS Windows). Spyder bringt auch schon etliche wichtige Module standardmäßig mit.

Python starten

[Bearbeiten]

MS Windows

[Bearbeiten]

Das Icon für das Python-Programm doppelklicken. Und schon startet das Programm.

Python im interaktiven Modus präsentiert sich dann so:

Python 3.12.4 (tags/v3.12.4:8e8a4ba, Jun  6 2024, 19:30:16) [MSC v.1940 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

Alternativ kann das Programm auch über die Eingabeaufforderung oder die PowerShell gestartet werden:

c:\devel\Python>python.exe
Python 3.12.4 (tags/v3.12.4:8e8a4ba, Jun  6 2024, 19:30:16) [MSC v.1940 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

Linux

[Bearbeiten]

Tippen Sie einfach das Wort „python“ (oder unter openSUSE Tumbleweed z.B. auch „python3.11“ oder „python3.13“) in einem Linux-Terminal ein, schließen den Befehl mit der RETURN-Taste ab, und schon startet Python im interaktiven Modus:

Python 3.13.12 (main, Feb 09 2026, 22:37:44) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 

Es gibt auch noch andere Möglichkeiten Python zwecks Programmausführung zu starten, z. B. den  Shebang (#!) am Beginn eines Python-Scripts. Das Script sei als Script.py gespeichert. Dann kann das Script mit ./Script.py ausgeführt werden. Für openSUSE Tumbleweed sei nachfolgend ein lauffähiges "Hallo Welt!"-Script angegeben. Es wird in diesem Script der Python-Interpreter in der Version 3.13 verwendet :

#!/usr/bin/python3.13
print("Hallo Welt!")

Die Berechtigungen zum Ausführen der Datei müssen natürlich noch richtig gesetzt werden, z.B. mittels chmod 777 Script.py.

Oder es wird in einen Pfad verschoben, in dem sich ausführbare Programme generell befinden (echo $PATH). Das Script kann dann wie ein normales Programm ohne weitere Angaben mit Script.py gestartet werden. Alternativ wird nicht das Script an sich verschoben, sondern nur ein symbolischer Link angelegt, z.B. mit ln -s ~/tmp/Script.py ~/.local/bin/Script.py.~/.local/bin sei ein im PATH gelegenes Verzeichnis. Dies sind aber schon Features für fortgeschrittene Linux-Benutzer und werden am Anfang eher selten benötigt.

Ein paar Worte zur Erklärung

[Bearbeiten]

Getestet wurden die Beispiele unter den Betriebssystemen

  • MS Windows 10 mit der Python-Version 3.12.0 (teilweise auch mit 3.12.2 und 3.13.1; nur die Inhalte die bis spätestens Juli 2025 erstellt wurden)
  • MS Windows 11 ab der Python-Version 3.13.4 (nur zum Teil; ab Juli 2025)
  • openSUSE Leap 15.6 mit der Python-Version 3.11.12 (Spyder, nur vereinzelt) und zum Teil mit 3.12.11 (ab Juli 2025 bis November 2025).
  • openSUSE Tumbleweed ab der Python-Version 3.13.9 (nur vereinzelt, ab November 2025)

An Beliebtheit rangiert Python mit Stand März 2026 mit einem Rating von 21,25% an 1. Stelle vor C und C++ (lt. TPCI - TIOBE Programming Community Index). Lt. GitHub Top 50 Programming Languages Globally lag Python im Q3/2025 auf Rang 2, vor TypeScript und hinter JavaScript. Der Name "Python" rührt von der Komikertruppe  Monty Python her. Die Icons für Python (z.B. Python selbst, Eric IDE, IDLE) sind aber durch die Python-Schlangenart symbolisiert.

Ein erstes Programm

[Bearbeiten]

Kommentare werden in Python mit der Raute (#) eingeleitet. Sie werden vom Python-Interpreter ignoriert. Text kann mit der print-Funktion ausgegeben werden. Starten Sie Python und geben sie folgende Anweisungen zeilenweise ein

>>> # Das ist ein Kommentar
>>> print("Hallo Welt!")

Als Ergebnis erhalten Sie

Hallo Welt!

Der Prompt (>>>) ist selbstverständlich nicht einzutippen, sondern wird vom Python-System geliefert.

Strings können in Python entweder in Anführungszeichen (") gesetzt werden oder in Hochkommatas('). In diesem Text wird die erste Variante bevorzugt eingesetzt.

Im Gegensatz zu Julia ist es hier egal, ob zwischen print und der öffnenden Klammer Leerzeichen stehen.

Python als Taschenrechner

[Bearbeiten]

Allgemeines

[Bearbeiten]

Wir wollen 3 * 5 berechnen. Dazu starten wir Python im interaktiven Modus. Geben Sie dann die Formel

>>> 3 * 5

ein, drücken die Taste ENTER/RETURN () und erhalten als Ergebnis

15

Auch kompliziertere Ausdrücke sind möglich. Beispielsweise mit Winkelfunktionen, Quadratwurzeln etc. Wir wollen nun den Ausdruck berechnen :

>>> import math
>>> math.sin(math.sqrt(15))
-0.6679052983383519

Als erstes wird das math-Modul importiert. Dann wird der mathematische Ausdruck berechnet.

Eine andere Variante, die dasselbe Ergebnis liefert, ist

>>> from math import *
>>> sin(sqrt(15))
-0.6679052983383519

Es wird also aus dem Modul math alles importiert (erkennbar am *). Will man nicht alles importieren, so kann man das auch einschränken:

>>> from math import sin, sqrt

Beenden lässt sich das Python-Programm durch Eingabe von exit() (und natürlich ist zur Bestätigung die RETURN-Taste zu drücken).

Die Hilfefunktion von Python

[Bearbeiten]

Bei Eingabe der Anweisung help() springt Python in den Hilfemodus.

Eingabe:

>>> help()

Eingabe:

help> math.sin

Ausgabe:

Help on built-in function sin in math:

math.sin = sin(x, /)
    Return the sine of x (measured in radians).

Für die komplette Python-Dokumentation siehe [3]. Verlassen kann man den Hilfemodus durch das Drücken von STRG-C.

Aufgaben

[Bearbeiten]
  • Erkunden Sie die Tangensfunktion "tan" mittels Python-Hilfe (vergessen Sie nicht das math-Modul zu importieren und das math. vor tan)
  • Berechnen Sie mit Python den Ausdruck . Siehe für die Exponentialfunktion im Python-Hilfesystem auch den Befehl math.exp. Alternativ kann auch die Konstante math.e eingesetzt werden. Potenzieren kann man bei Python mit dem **-Operator (z.B. 2**3 = 8). Für gibt es math.pi.

Python als Scriptsprache

[Bearbeiten]

Häufig wird man aber kompliziertere Anweisungsfolgen verarbeiten müssen. Diese will man normalerweise nicht jedesmal neu eingeben, sondern in einer Datei speichern und diese Datei dann zur Ausführung bringen. Speichern Sie dazu folgenden Code in einer Textdatei, z.B. unter MS Windows als c:\tmp\test1.py

# Das ist ein Kommentar
print("Hallo Welt!")

Python-Dateien werden mit der Dateiendung .py versehen. Achten Sie darauf, dass vor dem print keine Leerzeichen vorhanden sind. Das ist eine Python-Eigenheit. Wie wir später sehen werden, nutzt Python Einrückungen als syntaktisches Mittel, z.B. um bei Schleifen den Schleifenkörper zu kennzeichnen.

Danach bringen Sie die Skriptdatei test1.py (sozusagen das Hauptprogramm) folgendermaßen zur Ausführung:

1) Starten Sie unter MS Windows die Eingabeaufforderung (oder alternativ auch die Windows PowerShell). Das sieht dann etwa so aus:

Microsoft Windows [Version 10.0.19045.3693]
(c) Microsoft Corporation. Alle Rechte vorbehalten.

C:\Users\xyz>
Falls jemand nicht weiß, wie man die Eingabeaufforderung startet: Eine Möglichkeit ist, einfach in der Taskleiste von Windows das "Start"-Symbol  ()  mit der rechten Maustaste anklicken. "Ausführen" auswählen (oder alternativ für die PowerShell unter Windows 10 den Eintrag "Windows PowerShell", unter Windows 11 den Eintrag "Terminal"). Im sich öffnenden Dialogfenster gibt man in die "Öffnen"-Zeile das Wort cmd ein und mit "OK" wird das Ganze bestätigt.

2) Wechseln Sie mittels cd c:\tmp in das Verzeichnis c:\tmp

3) Angenommen, Sie haben Python unter dem Pfad c:\devel\Python\ installiert. Starten Sie das Programm so (der Prompt c:\tmp>ist natürlich nicht mit einzutippen):

c:\tmp>c:\devel\Python\python.exe test1.py

4) Wie erwartet ergibt sich folgende Ausgabe am Bildschirm

Hallo Welt!

Die Vorgehensweise unter Linux ist prinzipiell gleich. Die kleinen Unterschiede, wie z.B. der Slash statt dem Backslash in Pfadangaben, sollten für Linux-Benutzer keine Hürde darstellen.

Variablen

[Bearbeiten]

Variablenbezeichner können aus Buchstaben (A-Za-z), Ziffern (0-9) und Underscores (_) bestehen, dürfen aber nicht mit einer Zahl beginnen. Führende Underscores haben u.a. im Kontext mit der Objektorientierten Programmierung eine spezielle Bedeutung und sollten nicht für "normale" Variablenbezeichner verwendet werden.

Gültige Variablenbezeichner wären also:

xyz
x1
_wert
name_anzahl

Es gibt in Python etliche Schlüsselwörter (z.B. for, if oder return). Diese dürfen nicht als eigene Variablenbezeichner verwendet werden. Eine Liste aller Schlüsselwörter liefert das Script

import keyword
print(keyword.kwlist)

Übung: Speichern Sie dieses Script in eine Datei, z.B. in c:\tmp\test1.py. Führen Sie diese Datei aus, um die Liste der Schlüsselwörter auszugeben.

Da Python case-sensitiv ist, repräsentieren folgende Bezeichner verschiedene Variablen:

xyz
XYZ
xYz

Werte werden an Variablen mittels Gleich-Zeichen (=) zugewiesen. Im Folgenden wird der Code immer in der Datei c:\tmp\test1.py gespeichert.

x = 5
y = 10
z = x*y
print(z)

Bringen Sie die Datei test1.py zur Ausführung so erhalten Sie folgende Bildschirmausgabe

50

Sie können auch mehrere Anweisungen in einer Zeile durch Semikolon getrennt schreiben. Dies führt aber zu unübersichtlichem Code.

x = 5; y = 10; z = x*y; print(z)

Ausgabe:

50

Auch aus der Programmiersprache C/C++ oder Java bekannte Konstrukte können Sie verwenden, z.B.

x = 5
# x = x - 2
x -= 2
print(x)

Bildschirmausgabe:

3

Beachten Sie, dass mit dem =-Zeichen eine Wertezuweisung durchgeführt wird. Dies ist nicht äquivalent zum mathematischen =-Zeichen, wie am vorigen Beispiel zu ersehen ist. Den Inkrement-/Dekrementoperator (z.B. x++ oder x--) aus C/C++ oder Java kennt Python aber nicht.

Variablen sind nicht an einen bestimmten Datentyp gebunden, folgendes ist mit Python problemlos möglich:

import math
wert = 10
print(wert)
wert = 35.5
print(wert)
wert = "Hallo"
print(wert)
wert = math.pi
print(wert)

Ausgabe:

10
35.5
Hallo
3.141592653589793

Physische und logische Zeilen

[Bearbeiten]

In Python muss eine Anweisung in einer logischen Zeile Platz finden. Wird eine Anweisung aber zu lang für eine Zeile, dann kann sie in mehrere physische Zeilen unterteilt werden. Dies kann einerseits durch einen Backslash am Ende einer Zeile geschehen, z.B.

a = 2 + \
5

Dies stellt eine logische Zeile dar, die in zwei physische Zeilen unterbrochen ist.

Geklammerte Ausdrücke werden automatisch zu einer logischen Zeile verbunden, z.B.

a = (2 + 
5)

Achtung: Im ersten Beispiel darf nach dem Backslash nichts mehr stehen, auch kein Kommentar. Dies trifft im zweiten Bespiel nicht zu, hier könnte noch ein Kommentar folgen, z.B.

a = (2 +    # Kommentar 
5)

Auch für Strings gibt es Möglichkeiten, diese auf mehrere Zeilen aufzuspalten.

# Kurzer String
str1 = "ABC"

# Langer String
str2 = """Hallo Welt,
Grüetzi Schwyzer,
Servus an alle"""

# Backslash
str3 = "UVW\
XYZ"

# Mit Klammern
str4 = ("Sehr langer Text, der automatisch .............. "
        "in einer einzigen Variable zusammengefügt wird."
)

print(str1)
print(str2)
print(str3)
print(str4)

Ausgabe:

ABC
Hallo Welt,
Grüetzi Schwyzer,
Servus an alle
UVWXYZ
Sehr langer Text, der automatisch .............. in einer einzigen Variable zusammengefügt wird.

Hexadezimale, oktale, binäre und andere Zahlen

[Bearbeiten]
d = 1050         # Dezimalzahl
h = 0xAA2        # Hexadezimalzahl
o = 0o12         # Oktalzahl
b = 0b100001101  # Binärzahl

print(d)
print(h)
print(o)
print(b)

Ausgabe:

1050
2722
10
269

Groß- und Kleinbuchstaben sind in obigen Literalen übrigens egal. So kann man z.B. statt 0b1001 auch 0B1001 schreiben (siehe dazu [4]).

Sie können auch dezimale in hexadezimale Zahlen umwandeln, usw.:

h = hex(1050)    # Dezimalzahl -> Hexadezimalzahl
b = bin(1050)    # Dezimalzahl -> Binärzahl
o = oct(1050)    # Dezimalzahl -> Oktalzahl
print(h)
print(b)
print(o)

Ausgabe:

0x41a
0b10000011010
0o2032

Gegeben sei die Zahl 121 zur Basis 3. Diese soll in eine Dezimalzahl umgewandelt werden. Das kann so geschehen:

z = int("121", 3)
print(z)

Ausgabe:

16

Dass dies richtig ist, davon kann man sich folgendermaßen überzeugen:


Zahlen übersichtlicher schreiben kann man auch mittels Underscore, z.B.:

print("Eine Million (Variante 1) =", 1000000)
print("Eine Million (Variante 2) =", 1_000_000)
print("Eine Rechnung:", 2_000 * 400_000);

Es ergibt sich bei beiden Varianten die gleiche Ausgabe. Variante 2 ist aber im Sourcecode leichter lesbar, detto die Zahlen in der Rechnung:

Eine Million (Variante 1) = 1000000
Eine Million (Variante 2) = 1000000
Eine Rechnung: 800000000

Strings und Platzhalter

[Bearbeiten]

Ein paar einfache Beispiele:

print("Hallo {}" . format("Hugo"))
print("Hallo {:s}" . format("Hugo"))
print("Hallo %s" % "Hugo")

Ausgabe:

Hallo Hugo
Hallo Hugo
Hallo Hugo

Python-Code (formatted string literals):

str1 = "Hallo"
str2 = "Hugo"
print(f"{str1} {str2}")

Ausgabe:

Hallo Hugo

Komplexere Beispiele:

print("Hallo {} und {}" . format("Hugo", "Mike"))
print("Hallo {name1} und {name2}" . format(name2="Hugo", name1="Mike"))
# Füllzeichen: *
# Bündigkeit: > (=rechts), < (=links), ^ (=zentriert)
# Feldweite: 10
# Typ: s (=String), f (=Gleitkommazahl), d (=Dezimalzahl) etc.
print("Hallo {:*>10s}" . format("Hugo"))
print("Hallo {:*<10s}" . format("Hugo"))

Ausgabe:

Hallo Hugo und Mike
Hallo Mike und Hugo
Hallo ******Hugo
Hallo Hugo******

Python-Code:

str = "Hallo\t%s\t%7.2f\t%10.2e\t%i" % ("Hugo", 12.34567, 34.567, 264)
print(str)

Ausgabe:

Hallo	Hugo	  12.35	  3.46e+01	264

Python-Code:

wert = 11.567
print(f"Ausgabe: {wert:.5f}")

Ausgabe:

Ausgabe: 11.56700

Unicode

[Bearbeiten]

Neben den bekannten ASCII-Zeichen lassen sich Zeichen auch mittels Unicode beschreiben. Griechische Buchstaben oder komplexere mathematische Operatoren - all das sollte kein Problem sein. Siehe auch  Unicode,  Liste der Unicodeblöcke und  Unicodeblock Mathematische Operatoren. Im Folgenden werden ein paar Zeichen (Allquantor, Nabla-Operator, Existenzquantor), die man aus der Mathematik kennt, erzeugt.

ch1 = "\N{FOR ALL}"
ch2 = "\N{NABLA}"
ch3 = "\u2203"
print(ch1, ch2, ch3)

Ausgabe:

∀ ∇ ∃

Diese Ausgabe ergibt sich z.B. mit der IDLE-Shell oder mit Cygwin. Beim Ausführen über die Windows-Eingabeaufforderung oder Windows PowerShell unter MS Windows 10 erfolgt keine korrekte Darstellung. IDLE ist die mit Python mitgelieferte IDE (Integrated Development Environment, Integrierte Entwicklungsumgebung). Gegen Ende dieses Textes wird IDLE kurz beschrieben. Das Problem mit der Windows Eingabeaufforderung lässt sich aber umgehen. Man muss nur eine Schriftart auswählen, die die Zeichen kennt, z.B. "DejaVu Sans Mono". Dazu klicken Sie einfach bei der Eingabeaufforderung mit der rechten Maustaste oben auf die weiße Leiste und wählen im aufpoppenden Fenster den Menüpunkt "Eigenschaften". Es öffnet sich ein Dialogfenster. Über den Reiter "Schriftart" lässt sich nun die Schriftart einstellen. Unter MS Windows 11 oder openSUSE Leap 15.6 (bash-Konsole) gibt es dieses Problem ohnehin nicht.

Reguläre Ausdrücke

[Bearbeiten]

Python kennt auch  reguläre Ausdrücke. Dazu gibt es in Python das Modul re. Beipielsweise sollen alle Zahlen () in einem String gesucht und ausgegeben werden. Als String sei gegeben: 3x Grüße und 100 Kekse. Das Muster (Pattern) ist \d+. \d steht für eine Dezimalziffer 0-9. Das Plus-Zeichen (+) steht symbolisch für ein oder mehrere Zeichen des vorherigen Ausdrucks. Hier also ein oder mehrere Dezimalziffern. Es wird die Funktion findall aus dem Modul reverwendet.

Python-Code:

from re import findall

str = "3x Grüße und 100 Kekse."
pat = "\\d+"  # Doppel-Backslashes müssen verwendet werden, sonst gibt Python eine Warnung aus!
              # alternativ: pat = r"\d+" 
              # oder: pat = "[0-9]+"

numb = findall(pat, str)
print(numb)

Ausgabe:

['3', '100']

Python kennt noch viele weitere Möglichkeiten mittels regulärer Ausdrücke zu hantieren. Dies soll hier aber nicht vertieft werden, da das Thema schon ziemlich speziell und komplex ist. Bei Bedarf siehe aber z.B. die Bücher Weigend, Seite 380ff und Ernesti, Kaiser [5] oder die Python-Dokumentation [6]. Auch Python unter Linux: Reguläre Ausdrücke liefert ein umfangreiches und brauchbares Python-2-Kapitel zu den regulären Ausdrücken. Die dort gelisteten Beispiele müssten ggf. vor Verwendung auf Python-3 umgeschrieben werden. Wie macht man das? Dazu siehe z.B. [7], [8] oder [9]

Es gibt auch ein externes Modul regex, das bei Bedarf extra installiert werden muss ([10]). Es bietet zusätzliche Funktionalität und gründlicheren Unicode-Support. Dies sei hier aber nur der Vollständigkeit halber erwähnt.

Verzweigungen

[Bearbeiten]

Die IF-Verzweigung ist aus anderen Programmiersprachen bereits bekannt. In Pseudocode lässt sie sich folgendermaßen darstellen:

WENN bedingung TRUE
  führe block1 aus
SONST
  führe block2 aus
ENDE 

In Python gibt es keinen expliziten ENDE-Kennzeichner. Stattdessen wird der Code durch Einrückungen strukturiert. Alles mit der gleichen Einrückungstiefe gehört zum selben Block. Dies zeichnet Python vor anderen Programmiersprachen aus.

Die test1.py-Datei laute also wie folgt:

x = 5

if x < 4:
  print("x ist kleiner als 4")
else:
  print("Der else-Zweig wird ausgefuehrt")
  print("x ist groesser oder gleich 4")  

Ausgabe:

Der else-Zweig wird ausgefuehrt
x ist groesser oder gleich 4

Man achte auch auf die Doppelpunkte in der if- und else-Zeile. Darauf vergisst man gerne, wenn man von anderen Programmiersprachen kommt.

Folgendes wäre in Python ein Fehler (genauer gesagt ein IndentationError).

x = 5

if x < 4:
  print("x ist kleiner als 4")
else:
  print("Der else-Zweig wird ausgefuehrt")
    print("x ist groesser oder gleich 4")  

Auch Nachstehendes würde nicht zum gewünschten Ergebnis führen (löst aber keine Fehlermeldung aus). Der letzte print-Befehl ist schon außerhalb der IF-ELSE-Verzweigung.

x = 3

if x < 4:
  print("x ist kleiner als 4")
else:
  print("Der else-Zweig wird ausgefuehrt")
print("x ist groesser oder gleich 4")

Ausgabe:

x ist kleiner als 4
x ist groesser oder gleich 4

Python kennt eine Reihe von Vergleichs- und Verknüpfungsoperatoren:

   <, <= ... kleiner (gleich)
   >, >= ... größer (gleich)
   == ... gleich
   != ... ungleich
   is ... identisch
   is not ... nicht identisch
   and ... AND
   or ... OR
   not ... NOT

Beispielsweise:

a = 5
b = 9

if a<=10 and b!=7:
  print("OK")
else
  print("Nicht OK")

Ausgabe:

OK

Der else-Block kann übrigens auch ersatzlos entfallen.

Mehrfache Verzweigungen werden durch das elif-Konstrukt erstellt.

a = 14

if a<=10:   
  print("<=5")
elif a>11 and a<15:
  print("11 bis 15")
elif a>16 and a<20:
  print("16 bis 20")
else:
  print(">=20")

Ausgabe:

11 bis 15

In Python gibt es auch die Schlüsselwörter True (für wahr) und False (für falsch). Man beachte, dass sie mit Großbuchstaben beginnen. Andere Schreibweisen wären ein Fehler. Sie gehören zum Datentyp bool. Ihnen sind auch die Zahlen 1 und 0 zugewiesen.

match

[Bearbeiten]

Ab Python 3.10 gibt es auch die match-Anweisung. Dies ist das Python-Pendant für die switch-Anweisung in anderen Programmiersprachen, geht aber bei näherer Betrachtung weit darüber hinaus. Hier nur ein einfaches Beispiel:

x = "Hello"

match x:
    case "Servus" | "Ciao":         # or
        print("Servus an alle")
    case "Grüetzi":
        print("Grüetzi Schwyzer")  
    case _:                         # other, default, sonstiges ...
        print("Hallo Welt")

Ausgabe:

Hallo Welt

Für nähere Details siehe z.B. [11], [12], [13] und das Python Enhancement Proposal (PEP) 636 – Structural Pattern Matching: Tutorial [14] und dort insbesondere den Anhang A - Quick Intro.

match, case, _ etc. sind sogenannte soft keywords. Im Gegensatz zu den normalen Schlüsselwörtern dürfen ihnen auch Werte zugewiesen werden. Eine Liste der weichen Schlüsselwörter lässt sich durch keyword.softkwlist erstellen (die Anweisung gibt es seit Python 3.9). Siehe dazu auch [15] und [16].

Schleifen

[Bearbeiten]

while

[Bearbeiten]

Die WHILE-Schleife ist kopfgesteuert. Sie funktioniert wie aus anderen Programmiersprachen bekannt.

In Pseudocode:

SOLANGE bedingung TRUE
  führe block aus
ENDE

In Python:

x = 0

while x <= 10:
  print(x)
  x += 1

Ausgabe:

0
1
2
3
4
5
6
7
8
9
10
for x in range(6):
  print(x*2)

Ausgabe:

0
2
4
6
8
10

Die Schleife läuft von 0 bis 5. Ausgegeben wird jeweils der Wert x*2. Aquivalent kann diese Schleife auch so geschrieben werden:

for x in range(0, 11, 2):
  print(x)

Die Ausgabe ist wie oben. Der Startwert sei 0, der Endwert ist 11-1 und die Schrittweite ist 2.

Ein anderes Beispiel sei

for x in "text":
  print(x)

Ausgabe:

t
e
x
t

Schleifen abbrechen

[Bearbeiten]

break

[Bearbeiten]

break bricht die Schleife ab und setzt mit dem nächsten Befehl außerhalb der Schleife fort.

for var in range(100):
  print(var) 
  if var == 5:
    break

Ausgabe:

0
1
2
3
4
5

continue

[Bearbeiten]

continue bricht den aktuellen Schleifendurchlauf ab und setzt mit dem nächsten Schleifendurchlauf fort.

for var in range (11):
  if var == 5:
    continue
  print(var)

Ausgabe:

0
1
2 
3
4
6
7
8
9
10

try - except

[Bearbeiten]
try:
    z1 = 12 / 0
    print(z1)
except ZeroDivisionError:
    print("Das Ergebnis ist unendlich")
except:
    print("Kann nicht berechnet werden!")
    print("Bitte die Formel korrigieren!")

Ausgabe:

Das Ergebnis ist unendlich

Es wird versucht, eine Zahl durch Null zu dividieren. Das ist nicht möglich, es wird eine Ausnahme ausgelöst. Das Programm springt daher in den except-ZeroDivisionError-Block und führt die dort gelisteten Anweisungen aus (in unserem Fall eine print-Anweisung). Würden wir dieses Programm ohne try-except ausführen, so ergibt sich aus

z1 = 12 / 0
print(z1)

folgende Fehlermeldung und ein unmittelbarer Programmabbruch

Traceback (most recent call last):
  File "C:\tmp\test1.py", line 1, in <module>
    z1 = 12 / 0
ZeroDivisionError: division by zero

Mit dem try-except-Mechanismus können also Ausnahmen oder Fehler aufgefangen und behandelt werden. In unserem Beispiel ist das eher trivial, aber bei größeren Programmen kann das durchaus Sinn machen.

Ein leerer Block muss in Python mittels dem Schlüsselwort pass dargestellt werden. Z.B.

x = 2

if x == 1:
    print("Wert ist ", x)
else:
    pass

Würde man das pass im else-Block weglassen, so würde man eine Fehlermeldung erhalten:

IndentationError: expected an indented block after 'else' statement on line 5

Funktionen

[Bearbeiten]

Aufrufen von Funktionen

[Bearbeiten]

Funktionen sind uns im Rahmen dieses Kurses schon zuhauf begegnet. Sei es die print()-, die math.sin()- oder die hex()-Funktion. All diese Funktionen werden von Python zur Verfügung gestellt, ohne dass man sie explizit programmieren müsste. Aufgerufen werden diese Funktionen, indem man ihren Namen eintippt, gefolgt von runden Klammern. In diesen Klammern können noch Argumente übergeben werden. Auch Rückgabewerte sind möglich.

Funktionen selber schreiben

[Bearbeiten]

Funktionen werden mit dem def-Schlüsselwort (man definiert die Funktion) eingeleitet, danach folgt der Funktionsname, danach wiederum runde Klammern, in denen formale Argumente stehen können. Abgeschlossen wird die def-Zeile mit einem Doppelpunkt. Danach folgt der Funktionskörper. Dieser Funktionskörper muss wiederum eingerückt werden (wie von den Verzweigungen und Schleifen bekannt). Aufgerufen wird diese Funktion, indem man ihren Funktionsnamen eingibt, gefolgt von runden Klammern (ggf. mit den aktuellen Parametern). Z.B.

# Funktion definieren
def halloWelt(i):
    # i ... beliebige Ganzzahl
    print("Hallo " * i, end="")
    print("Welt!")
   
# Funktion aufrufen
halloWelt(3)

Ausgabe:

Hallo Hallo Hallo Welt!

Unterschied zwischen formalen und aktuellen Parametern:

Aktuelle Parameter werden auch Argumente genannt.

Rückgabe von Funktionswerten:

# Funktion definieren
def mathFunc(a, b):
    r1 = a + b
    r2 = a * b
    return r1, r2
   
# Funktion aufrufen
a, b = mathFunc(3, 5)

# Ausgabe der zurückgegebenen Werte
print(a)
print(b)

Ausgabe:

8
15

Vorgabeparameter, z.B.:

def mathFunc(a=10, b=20):
    r1 = a + b
    r2 = a * b
    return r1, r2
   
a, b = mathFunc(3, 5)
print(a)
print(b)

a, b = mathFunc(5)
print(a)
print(b)

a, b = mathFunc(b=6)
print(a)
print(b)

Ausgabe:

8
15
25
100
16
60

Lambda-Funktionen

[Bearbeiten]
print((lambda a, b: a*b) (3, 5))

Ausgabe:

15

Eingeleitet wird eine Lambda-Funktion (auch Lambda-Form, Lambda-Operator oder anonyme Funktion genannt) mit dem Schlüsselwort lambda. Es folgen die formalen Argumente, danach ein Doppelpunkt, die Berechnungsvorschrift und ggf. abschliessend in Klammern die aktuellen Parameter.

Man kann einer Lambda-Funktion auch einen Funktionsnamen geben und die Funktion über diesen Namen aufrufen, z.B.

prod = lambda a, b: a*b
print(prod(3, 5))

Als Ausgabe wird wieder die Zahl 15 geliefert.

Rekursive Funktionen

[Bearbeiten]

Funktionen können wiederum andere Funktionen aufrufen. Von einem rekursiven Funktionsaufruf spricht man, wenn die aufgerufene Funktion gleich der aufrufenden ist.

def printFunc(i):
    if (i >= 5):
        return 
    else:
        print("Hallo Welt")
        printFunc(i+1)
        
printFunc(1)

Ausgabe:

Hallo Welt
Hallo Welt
Hallo Welt
Hallo Welt

Funktionsannotationen

[Bearbeiten]

Python ist sehr flexibel, was Typen angeht. Im Vorhergehenden haben wir generell keine Typangaben gemacht. Will man Typen angeben, so bietet Python das Konzept der Funktionsannotation.

def calcFunc(a: int, b: int) -> int:
    return a+b

r1 = calcFunc(8, 9)
r2 = calcFunc(8.0, 9.0)
r3 = calcFunc("Hallo", "Welt")

print(r1)
print(r2)
print(r3)

Ausgabe:

17
17.0
HalloWelt

Jetzt sieht man auf den ersten Blick, welche Typen der Programmierer im Sinn hatte, als er die Funktion erstellte. Das Problem dabei ist nur, dass es Python ziemlich egal ist, welche Typen man im Endeffekt eingibt. Im obigen Beispiel können statt Integer-Typen u.a. auch Float- oder String-Typen eingegeben werden.

Siehe zum Thema "Type Checking" aber auch den später folgenden Abschnitt Ing_Mathematik:_Python#Type_Checker.

Variadische Funktionen

[Bearbeiten]

Python-Code:

def test1(a, *b):
    print(a);
     
    for c in b:
        print(c);
       
test1("Hallo", "Welt", "Schweizer", "und alle anderen")

Ausgabe:

Hallo
Welt
Schweizer
und alle anderen

Mit dem Stern (auch als Splat-Operator bezeichnet) in der formalen Parameterliste bei der Funktion test1 wird angezeigt, dass eine beliebige Anzahl von Argumenten übergeben wird. Dies entspricht in etwa dem, was in anderen Programmiersprachen (PHP etc.) mittels Ellipse (...) angezeigt wird.

Tupel, Listen und andere

[Bearbeiten]
Datentypen und Strukturen

Tupel, Listen und einige andere sind Datenstrukturen oder Sequenzen.

Listen (z.B. eine Einkaufsliste) sind veränderbar (mutable). Ein Tupel kann dagegen nicht verändert werden (immutable). Listen werden beim Anlegen in eckige Klammern eingeschlossen, Tupel in runde Klammern. Beim Tupel können die Klammern auch weggelassen werden. Ein Tupel mit nur einem Element muss mit einem Beistrich abgeschlossen werden. Der Grund ist, dass Python sonst nicht entscheiden kann, ob ein Tupel angelegt werden soll, oder nur ein geklammerter Wert. Nachfolgend werden einige Operationen mit Listen und Tupel dargestellt.

Als Gedächtnisstütze kann man sich den Unterschied zwischen Tupel und Liste ev. so leichter merken:

Tupel ... runde Klammern, unveränderlich
Liste ... eckige Klammern, veränderlich.
# Liste und Tupel
liste = [1, 2, "Hallo"]
tupel = (1, 2, "Hallo") 

# Ausgabe von liste und tupel
print(liste)
print(tupel)

# Ausgabe von Einzelelementen
print(liste[1])
print(tupel[2])

# Element an Liste anhängen und einfügen 
liste.append(55)
liste.insert(4, "Welt")
print(liste)

# Element aus Liste entfernen
liste.remove(1)
print(liste)

# einige weitere Beispiele
liste2 = [1,]
tupel2 = 1, 2
tupel3 = (1,) 
print(liste2)
print(tupel2)
print(tupel3)

Ausgabe:

[1, 2, 'Hallo']
(1, 2, 'Hallo')
2
Hallo
[1, 2, 'Hallo', 55, 'Welt']
[2, 'Hallo', 55, 'Welt']
[1]
(1, 2)
(1,)

Beispiel:

woerter = ["Hallo", "Welt"]
satz = " ".join(woerter)
print(satz)

Ausgabe:

Hallo Welt

Zu den Datenstrukturen gehören weiters auch Mengen und Dictionaries. Mengen sind von der Mathematik bekannt, sie sind ungeordnet und es kommen keine mehrfachen Elemente vor. Dictionaries sind durch Schlüssel :Wert-Paare gekennzeichnet. Mengen werden beim Anlegen wie Dictionaries in geschweifte Klammern eingeschlossen.

dict = {"vorname":"Hugo", "nachname":"Meister" }
menge = {1, 1, 3, 4, 4, 4, "Hallo"}

print(dict)
print(menge)
print(dict["vorname"])

Ausgabe:

{'vorname': 'Hugo', 'nachname': 'Meister'}
{1, 3, 4, 'Hallo'}
Hugo

Geschweifte Klammern ohne Inhalt stellen Dictionaries dar und keine Mengen:

di = {}
print(type(di))

Ausgabe:

<class 'dict'>

List Comprehensions

[Bearbeiten]

Aus einer Eingabeliste soll eine Ausgabeliste erzeugt werden. Das kann folgendermaßen geschehen.

Mathematische Schreibweise:

Python-Code:

lc = [x*2 for x in range(1,11)]
print(lc)

Ausgabe:

[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Mathematische Schreibweise:

Python-Code:

lc = [x*2 for x in range(1,11) if x%2 == 0]
print(lc)

Ausgabe:

[4, 8, 12, 16, 20]

Siehe auch  List Comprehension.

Set Comprehensions

[Bearbeiten]

Dies ist sehr ähnlich wie im vorigen Abschnitt beschrieben. Es wird aber keine Liste, sondern eine Menge erzeugt.

sc = {x*2 for x in range(1,11)}
print(sc)

Ausgabe:

{2, 4, 6, 8, 10, 12, 14, 16, 18, 20}

Listen zusammenführen - zip()

[Bearbeiten]
li1 = ["A", "B", "C", "D"]
li2 = [1, 2, 3, 4]
li3 = [5.5, 6.6, 7.7, 8.8]

z = zip(li1, li2, li3)
print(z)

li4 = list(z)
print(li4)

Ausgabe:

<zip object at 0x00000283B6C6AC80>
[('A', 1, 5.5), ('B', 2, 6.6), ('C', 3, 7.7), ('D', 4, 8.8)]

Generatorausdruck

[Bearbeiten]
g = (i*2 for i in range(1,11))
print(g)
t = tuple(g)
print(t)
print(t[1:3])

Ausgabe:

<generator object <genexpr> at 0x00000241D2A4A5A0>
(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
(4, 6)

Slicing

[Bearbeiten]

slice ... Scheibe, Teil, in Scheiben schneiden

Beispiel: Zugriff auf Elemente eines geordneten sequentiellen Objekttyps (Liste, Tupel oder String):

str1 = "Hallo"
# Das erste Element wird mit dem Index 0 angesprochen
# [start (inkl.) : stop (exkl.) : step (default=1)]
str2 = str1[0:2]
# Alternativ auch: str2 = str1[:2] 
print(str2)

tup1 = (0,1,2,3)
# Das letzte Element hat auch den Index -1, das vorletzte den Index -2 usw.
tup2 = tup1[-3:-1]
print(tup2)

lst1 = [[1,  5,  10, 20],
        [30, 40, 50, 60]]
lst2 = lst1[1][1]
print(lst2)

Ausgabe:

Ha
(1, 2)
40

Beispiel: Umdrehen von Strings

str1 = "Hallo"
str2 = str1[::-1]
print(str2)

Ausgabe:

ollaH

Objektorientierte Programmierung

[Bearbeiten]

Eine einfache Klasse

[Bearbeiten]

class Fahrzeug:
    raeder = 4
   
    def __init__(self, geschwindigkeit, leistung):
        self.__geschwind = geschwindigkeit
        self.__leistung = leistung
        
    def setGeschwindigkeit(self, geschwindigkeit): # geschwindigkeit in km/h
        self.__geschwind = geschwindigkeit
        
    def setLeistung(self, leistung):
        self.__leistung = leistung
        
    def convertGeschw(self):
        # geschwindigkeit in m/s rueckgeben
        return self.__geschwind / 3.6
       

fahr = Fahrzeug(150, 90)

print(fahr.convertGeschw())

Ausgabe:

41.666666666666664

Die Klasse Fahrzeug wird durch das class-Schlüsselwort eingeleitet. raeder ist ein Klassenattribut und public. __init__ wird bei der Objekterzeugung automatisch aufgerufen. Man achte darauf, dass diese Methode immer mit zwei Unterstrichen eingeleitet und abgeschlossen wird. Instanzattributen wird das Wort self vorangestellt. Wir sehen uns z.B. das Attribut self.__geschwind an. Auch hier werden zwei Unterstriche verwendet. Das bedeutet, dass dieses Attribut private ist. Bei den Methoden wird immer self als erster Parameter angegeben. Beim Aufruf der entsprechenden Funktion wird das self aber nicht berücksichtigt.

Klassen importieren

[Bearbeiten]

Häufig ist es sinnvoll und übersichtlicher Klassen in eigenen Dateien zu speichern. Das sind dann eigene Module. Abgespeichert werden Sie mit der Endung py, wie bisher auch praktiziert. Aufgerufen werden Sie mit der import-Anweisung. Dann ist aber nur der Dateiname ohne Endung py zu verwenden. Klarer wird das mit einem Beispiel.

Datei c:\tmp\fahrzeug.py

class Fahrzeug:
    raeder = 4
   
    def __init__(self, geschwindigkeit, leistung):
        self.__geschwind = geschwindigkeit
        self.__leistung = leistung
        
    def setGeschwindigkeit(self, geschwindigkeit): # geschwindigkeit in km/h
        self.__geschwind = geschwindigkeit
        
    def setLeistung(self, leistung):
        self.__leistung = leistung
        
    def convertGeschw(self):
        # geschwindigkeit in m/s rueckgeben
        return self.__geschwind / 3.6

Datei c:\tmp\test1.py

import fahrzeug
fahr = fahrzeug.Fahrzeug(150, 90)
print(fahr.convertGeschw())

Ausgabe:

41.666666666666664

Die üblichen import-Anweisungen lauten wie folgt:

import-Befehl Instanz
import xyz xyz.Klasse
import xyz as x x.Klasse
from xyz import Klasse Klasse
from xyz import * Klasse

Der Vorteil der ersten beiden import-Anweisungen ist, dass es kaum zu Namenskollisionen kommen kann. Dafür hat man bei den letzten beiden Varianten weniger Tipparbeit.

Vererbung

[Bearbeiten]

Datei fahrzeug.py:

class Fahrzeug:
    raeder = 4
   
    def __init__(self, geschwindigkeit, leistung):
        self.__geschwind = geschwindigkeit
        self.__leistung = leistung
        
    def setGeschwindigkeit(self, geschwindigkeit): # geschwindigkeit in km/h
        self.__geschwind = geschwindigkeit
       
    def setLeistung(self, leistung):
        self.__leistung = leistung
       
    def convertGeschw(self):
        # geschwindigkeit in m/s rueckgeben
        return self.__geschwind / 3.6
       
       
class Luftfahrzeug(Fahrzeug):
    def __init__(self, geschwindigkeit, leistung, fluegel):
        super().__init__(geschwindigkeit, leistung)
        self.__flueg = fluegel
    
    def getFlueg(self):
        return self.__flueg

Datei test1.py:

import fahrzeug
fahr = fahrzeug.Luftfahrzeug(150, 90, 4)
print(fahr.getFlueg())

Ausgabe:

4

Grafiken zeichnen

[Bearbeiten]

Für das Zeichnen von Grafiken wird hier das Modul matplotlib verwendet. matplotlib ist ein externes Modul und muss vor der ersten Verwendung installiert werden. Das geht so:

  1. Starten Sie ein Terminal (bei Windows die Eingabeaufforderung).
  2. Führen Sie darin folgenden Befehl aus c:\devel\Python\Scripts\pip.exe install matplotlib

pip ist übrigens der Paketmanager von Python ( Pip_(Python)).

Optimalerweise installieren wir auch gleich das Modul numpy (Numerical Python). Wir werden es im Folgenden oft benötigen (nicht nur bei den Grafiken). Das funktioniert vom Prinzip her genauso, wie für matplotlib gezeigt.

Verwenden Sie Spyder, so sind diese Schritte nicht nötig. Spyder inkludiert diese Pakete standardmäßig. Unter openSUSE Tumbleweed lassen sich diese Pakete mittels YaST oder zypper installieren.

Graph einer Funktion

[Bearbeiten]

Es soll die cosh-Funktion im Intervall gezeichnet werden. Der Programmcode lautet in der einfachsten Form:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-3., 3.1, .1)
y = np.cosh(x)

plt.plot(x,y)
plt.grid()
plt.show()

Ausgabe:

Der Code ist quasi selbsterklärend. Das Untermodul pyplot des matplotlib-Moduls und das numpy-Modul werden importiert. x läuft von -3 bis +3. y wird für jeden x-Wert per Formel ausgerechnet. "plt.plot()" ist der Zeichenbefehl. "plt.show" ist notwendig, um das Fenster mit der Grafik anzuzeigen. Die Schrittweite 0.1 wurde so gewählt, um einen ausreichend glatten Verlauf des Graphen zu gewährleisten. Das ist immer ein Kompromiss zwischen Berechnungszeit und Ansehnlichkeit. Testen Sie einfach ein paar verschiedene Werte, um ein Gefühl dafür zu zu bekommen. "plt.grid()" zeichnet ein Gitter in die Grafik (kann auch weggelassen werden). Die Bezeichnungen plt und np könnten auch anders gewählt werden. Es ist aber Konvention, diese so wie hier gezeigt zu wählen.

Mit der im obigen Bild gezeigten Menüleiste kann die dargestellte Grafik nachträglich noch geändert werden (Zoom, Pan, Achsenparameter, Kurvenparameter etc.). Natürlich kann man das alles auch direkt programmieren. Wie das funktioniert wird ansatzweise etwas später gezeigt.

Ein etwas komplexeres Beispiel ist Folgendes:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-3., 3.1, .1)
y = np.cosh(x) + 2**x

plt.plot(x,y)
plt.grid()
plt.show()

Ausgabe:

Man beachte, dass im Gegensatz zu Octave und Julia der ominöse Punkt (.) bei 2**x mit Python nicht benötigt wird. Das macht das Programmiererleben etwas einfacher.

Graphen mehrerer Funktionen und weiteres

[Bearbeiten]
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-3., 3.1, .1)
y1 = np.cosh(x) + 2**x
y2 = np.sin(x) * np.cos(x)

plt.plot(x, y1, label = "cosh(x) + 2**x")
plt.plot(x, y2, label = "sin(x) * cos(x)")
plt.grid()
plt.title("Funktionsgraphen")
plt.xlabel("x")
plt.ylabel("y")
plt.legend(loc="best")

plt.show()

Um die Linienstile etwas individueller zu gestalten, ist folgender Programmcode gedacht:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-3., 3.1, .1)
y1 = np.cosh(x) + 2**x
y2 = np.sin(x) * np.cos(x)

plt.plot(x, y1, label = "cosh(x) + 2**x", lw=5, ls="dotted")
plt.plot(x, y2, label = "sin(x) * cos(x)", lw=3, ls="--")
plt.grid()
plt.title("Funktionsgraphen")
plt.xlabel("x")
plt.ylabel("y")
plt.legend(loc="best")

plt.show()

Funktion in Parameterdarstellung

[Bearbeiten]

Es soll die archimedische Spirale im Intervall gezeichnet werden.

import matplotlib.pyplot as plt
import numpy as np

t = np.arange(0., 6*np.pi, .1)
x = t * np.cos(t)
y = t * np.sin(t)

plt.plot(x, y)
plt.grid()
plt.title("Archimedische Spirale")
 
plt.show()

Diese Darstellung erscheint verzerrt. Will man gleiche Achsenskalierungen, so kann man den plt.axis()-Befehl verwenden.

import matplotlib.pyplot as plt
import numpy as np

t = np.arange(0., 6*np.pi, .1)
x = t * np.cos(t)
y = t * np.sin(t)

plt.plot(x, y)
plt.grid()
plt.title("Archimedische Spirale")
plt.axis("equal")

plt.show()

Funktion in Polardarstellung

[Bearbeiten]
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(projection="polar")
r = np.arange(0, 1, 0.01)
theta = r**3
line = ax.plot(theta, r)

plt.show()

Logarithmische Achsenskalierung

[Bearbeiten]

Semilog

[Bearbeiten]
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0., 10, .1)
y = 10**x

plt.plot(x, y)
plt.grid()
plt.semilogy()
plt.show()

Ausgabe:

LogLog

[Bearbeiten]
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0., 10, .1)
y = 10**x

plt.plot(x, y)
plt.grid()
plt.loglog()
plt.show()

Gefüllte Fläche

[Bearbeiten]
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 3, 0.1)

y1 = 3*x - 1
y2 = x**2

plt.plot(x, y1, x, y2, color='black')
plt.fill_between(x, y1, y2, where=y1>=y2)

plt.show()

Linien, Pfeile, Rechtecke, Kreise und Texte

[Bearbeiten]
import matplotlib as mpl
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

r = mpl.patches.Rectangle((0, 0), 3, 3, angle=30, fill=False)
c = mpl.patches.Circle((4, 4), 2, fill=False)

ax.add_patch(r)
ax.add_patch(c)
ax.plot([-2, 7], [-2, 0], color="black")
ax.arrow(0, 7, 5, 0, length_includes_head=True, head_width=0.5, head_length=1.5,
         color="black")

ax.set_aspect("equal")

plt.axis([-3, 8, -3, 8])
plt.show() 

Text kann mit ax.text(x, y, "Text") hinzugefügt werden, bspw.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

ax.text(0.1, 0.1, "Hallo")
ax.text(0.5, 0.5, "Welt", size="40", family="cursive", style="italic",
        rotation=30.0)

plt.show() 

Oder einfacher auch ohne subplots

import matplotlib.pyplot as plt

plt.text(0.1, 0.1, "Hallo")
plt.text(0.5, 0.5, "Welt", size="40", family="cursive", style="italic",
        rotation=30.0)

plt.show() 

Auch Sonderzeichen (griechische Buchstaben etc.) können verwendet werden (siehe dazu auch [17]).

import matplotlib.pyplot as plt

plt.text(.3, .5,
         r'$\Omega\ \psi\ \oint\ \nabla\ \dot a\ \frac{a}{b}\ a_b$',
         size="20")
plt.show() 

Jetzt wird noch gezeigt, wofür subplots sinnvoll eingesetzt werden können.

import matplotlib.pyplot as plt

fig, ax = plt.subplots(nrows=1, ncols=2)

ax[0].text(0.1, 0.1, "Hallo")
ax[1].text(0.1, 0.5, "Welt", size="40", family="cursive", style="italic",
           rotation=30.0)

plt.show()

Aufgaben

[Bearbeiten]
  • Zeichnen Sie die Strophoide . Das Ganze sollte in etwa so aussehen wie folgende Grafik:

  • Zeichnen Sie die verschlungene Hypozykloide . Das Ganze sollte in etwa so aussehen wie folgende Grafik:

  • Testen Sie bei den obigen Übungsaufgaben verschiedene Linienstile und Farben. Farben können mit dem plt.plot()-Parameter color gewählt werden.
  • Testen Sie bei den obigen Übungsaufgaben verschiedene Werte für a, c, r und R.

Räumliche Kurven

[Bearbeiten]
import matplotlib.pyplot as plt
import numpy as np

t = np.arange(0, 6*np.pi, 0.1)
x = t * np.cos(t)
y = t * np.sin(t)
z = t

fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
ax.plot(x, y, z)

plt.show()

Flächen

[Bearbeiten]
import matplotlib.pyplot as plt
import numpy as np 

x = np.arange(0, 10, 0.1)
y = np.arange(0, 10, 0.1)
x, y = np.meshgrid(x, y)
z = np.sin(x) + 3 * np.cos(y)

fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
ax.plot_surface(x, y, z)

plt.show()

Das Ganze in Netzdarstellung läßt sich so programmieren:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 10, 0.5)
y = np.arange(0, 10, 0.5)
x, y = np.meshgrid(x, y)
z = np.sin(x) + 3 * np.cos(y)

fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
ax.plot_wireframe(x, y, z)

plt.show()

Ein etwas komplexeres Beispiel:

import matplotlib.pyplot as plt
import numpy as np 

x = np.arange(0.1, 10, 0.1)
y = np.arange(0.1, 10, 0.1)
x, y = np.meshgrid(x, y)
z1 = np.sin(x) + 3 * np.cos(y)
z2 = np.sin(x) + np.log(y)
z3 = x + np.cos(y)
z4 = x**2 - y
 
fig, ax = plt.subplots(subplot_kw={"projection": "3d"}, nrows=2, ncols=2)

ax[0][0].plot_surface(x, y, z1)
ax[0][1].plot_surface(x, y, z2)
ax[1][0].plot_surface(x, y, z3)
ax[1][1].plot_surface(x, y, z4)

plt.show()

Man beachte, dass man die Unterbilder im Bild nach dem Ausführen des Scripts z.B. mit der mittleren Maustaste einzeln drehen, oder über die Einträge in der Menüzeile einzeln bearbeiten kann. Mit ein paar Zeilen Programmtext lässt sich also eine Menge an Funktionalität generieren.

Die Farbgebung lässt sich über colormaps variieren.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm

x = np.arange(0, 10, 0.1)
y = np.arange(0, 10, 0.1)
x, y = np.meshgrid(x, y)
z = np.sin(x) + 3 * np.cos(y)

fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
ax.plot_surface(x, y, z, cmap = cm.coolwarm)

plt.show()

Es gibt eine Menge an Colormaps, z.B. plasma, Greys, Dark2, ocean. Zwecks detaillierterer Infos siehe die matplotlib-Dokumentation. Verwendet man die IDE namens IDLE, so gibt es dort auch die automatische Codevervollständigung. D.h. es werden alle Möglichkeiten (in unserem Fall nach dem Eintippen von cm. alle verfügbaren Colormaps) angezeigt.

Die "edgecolor" und Linienbreite können auch frei gewählt werden:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm

x = np.arange(0, 10, 0.1)
y = np.arange(0, 10, 0.1)
x, y = np.meshgrid(x, y)
z = np.sin(x) + 3 * np.cos(y)

fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
ax.plot_surface(x, y, z, cmap = cm.coolwarm, edgecolor="black", linewidth=1.0)

plt.show()

Höhenlinien

[Bearbeiten]
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 10, 0.1)
y = np.arange(0, 10, 0.1)
x, y = np.meshgrid(x, y)
z = np.sin(x) + 3 * np.cos(y)

fig, ax = plt.subplots()
ax.contour(x, y, z)

plt.show()

Etwas abgewandelt sieht das so aus:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 10, 0.1)
y = np.arange(0, 10, 0.1)
x, y = np.meshgrid(x, y)
z = np.sin(x) + 3 * np.cos(y)

fig, ax = plt.subplots()
hl = ax.contour(x, y, z)
ax.clabel(hl, inline = True)

plt.show()

Und noch eine Variante (mit einem Farbbalken) sei gezeigt.

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 10, 0.1)
y = np.arange(0, 10, 0.1)
x, y = np.meshgrid(x, y)
z = np.sin(x) + 3 * np.cos(y)

fig, ax = plt.subplots()
hl = ax.contourf(x, y, z)
fig.colorbar(hl) 

plt.show()

Aufgaben

[Bearbeiten]
  • Zeichnen Sie die räumliche Kurve , , , .
  • Zeichnen Sie die Fläche .

Animationen

[Bearbeiten]

Mit matplotlib

[Bearbeiten]

Auch mit matplotlib sind Animationen möglich. Das ist ein bisschen komplizierter und wird deshalb hier nur mit einem sehr einfachen Beispiel dargestellt (bei Interesse siehe z.B. auch das Animations using Matplotlib-Tutorial).

import matplotlib.pyplot as plt
import matplotlib.animation as ani
import matplotlib
import numpy as np

def update(frame):
    line.set_xdata(x[:frame])
    line.set_ydata(y[:frame])
    return (line)

fig, ax = plt.subplots()

x = np.arange(0, 10, .1)
y = np.sin(x)

line, = ax.plot(x[0], y[0])
ax.set(xlim=[0, 10], ylim=[-1, 1])

a = ani.FuncAnimation(fig=fig, func=update, frames=100, interval=20)
plt.show()

# Speichere die Animation in einem animierten GIF (optional)
a.save(filename="c:/tmp/PythonIng_anim5.gif", writer="pillow")

Es wird eine Sinuskurve auf den Bildschirm gezeichnet. In der letzten Zeile wird diese Animation in ein animiertes GIF gespeichert. Das ist natürlich optional und kann auch weggelassen werden.

Mit VPython

[Bearbeiten]

Aber auch mit dem Modul VPython lassen sich einfache 3D-Animationen erstellen. VPython ist ein externes Modul, das vorab installiert werden muss. Unter openSUSE Tumbleweed gibt es dzt. kein entsprechendes rpm-Paket. Die übliche Methode der Installation mittels YaST oder zypper ist somit nicht möglich. Auch eine direkte Verwendung von pip führt nur zu einer Fehlermeldung (error: externally-managed-environment). Es empfiehlt sich dort folgende Vorgehensweise:

  1. Erstelle zuerst eine virtuelle Umgebung, z.B.: python3.11 -m venv ~/tmp/venv1
  2. Wechsle das Verzeichnis: cd ~/tmp/venv1/bin
  3. Installiere das entsprechende Paket: ./pip install vpython
  4. Führe das entsprechende Skript aus: ./python ~/tmp/test1.py

Aktuell (März 2026) ist dieses Programmpaket lt. der VPython-Homepage nur für die Python-Versionen 3.8 bis 3.12 verfügbar.

Ein Beispiel zu einer einfachen Animation wird nachfolgend geliefert.

from vpython import *

scene.width = 1200
scene.height = 600
scene.center = vector(20,0,0)
scene.background = color.white

cylinder(pos=vector(0,0,0), axis=vector(20,0,0), radius=5, 
        color=color.blue)
cone(pos=vector(0,0,0), axis=vector(-10,0,0), radius=5, 
        color=color.blue)
helix(pos=vector(20,0,0), axis=vector(40,0,0), radius=2, 
        coils=10, thickness=0.5, color=color.blue)

ball = sphere(pos=vector(20,0,0), color = color.green, radius = 1)
ball.p = vector(0.15, 0, 0)

toc = True

while True:
    rate(200)
    if(ball.pos.x <= 60 and toc == True):
        ball.pos += ball.p
    else:
        toc = False
        ball.pos -= ball.p
        if(ball.pos.x <= 20 and toc == False):
            toc = True

Idealerweise öffnet sich beim Ausführen des Scripts ein Browserfenster. Darin wird die programmierte Animation gezeigt (siehe auch den obigen Screenshot). Eine Größenänderung können Sie mit der mittleren Maustaste initiieren. Die Szenerie drehen können Sie mit der rechten Maustaste.

Mit VTK

[Bearbeiten]

Komplexer, aber auch mächtiger als VPython ist die Verwendung von VTK (Visualization Toolkit). Genauer gesagt des Python-Wrappers von VTK. Dieses externe Python-Modul muss vorab installiert werden (z.B. mittels YaST, pip oder in eine virtuelle Umgebung). VTK ist eine Softwarebibliothek zur 3D-Visualisierung und wurde ursprünglich in C++ geschrieben. Verbreitet eingesetzt wird diese Bibliothek in der Wissenschaft und Forschung, z.B.

  • in der medizinischen Bildgebung
  • für Strömungssimulationen
  • für Klimadaten

VTK funktioniert nach dem  Pipeline-Prinzip:

Source (Quellen) ->  Filter -> Mapper (Senken) -> Actor/Renderer

Daten fließen von den Quellen zu den Senken.

Als einfaches Beispiel wird die Darstellung eines Zylinders gezeigt, der mit den Maustasten gedreht oder in der Größe geändert werden kann:

import vtk

# Zylinder erzeugen
cyl = vtk.vtkCylinderSource()
cyl.SetRadius(5.0)
cyl.SetHeight(20.0)
cyl.SetResolution(40)

# Geometrie in darstellbare Daten umwandeln
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(cyl.GetOutputPort())

# Objekt in der Szene
actor = vtk.vtkActor()
actor.SetMapper(mapper)

# Szene verwalten
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)

# Render-Fenster
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)

# Maus/Tastatur-Steuerung
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(render_window)

# Starten
render_window.Render()
interactor.Start()

Ausgabe:

Gleiches Beispiel wie oben, aber mit einer Animationssequenz:

import vtk
import time

cyl = vtk.vtkCylinderSource()
cyl.SetRadius(5.0)
cyl.SetHeight(20.0)
cyl.SetResolution(40)

mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(cyl.GetOutputPort())

actor = vtk.vtkActor()
actor.SetMapper(mapper)

renderer = vtk.vtkRenderer()
renderer.AddActor(actor)

render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)

interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(render_window)

for i in range(360):
    actor.RotateZ(1)
    actor.RotateY(.5)
    render_window.Render()
    time.sleep(0.01)

Das Grafikfenster schließt sich nach Ablauf der Schleife. Das Fenster bleibt geöffnet, wenn Sie am Programmende folgenden Befehl hinschreiben

interactor.Start()

Um den animierten Zylinder grün einzufärben, müssen Sie Folgendes im obigen Programm ergänzen (Farbnamen):

colors = vtk.vtkNamedColors()
actor.GetProperty().SetColor(colors.GetColor3d("Green"))

Als Namen können Sie u.a. die CSS3 Web-Farben verwenden (siehe z.B. [18] und  Webfarbe#CSS_3).

Alternativ funktioniert auch das ( RGB):

actor.GetProperty().SetColor(0.0, 0.6, 0.0)

Wie der Zylinder mit einer Textur versehen wird, zeigt folgendes Programm:

import vtk
import time

cylinder = vtk.vtkCylinderSource()
cylinder.SetResolution(30)
cylinder.SetHeight(3.0)
cylinder.SetRadius(1.0)
cylinder.CappingOn()

texture_coords = vtk.vtkTextureMapToCylinder()
texture_coords.SetInputConnection(cylinder.GetOutputPort())
texture_coords.PreventSeamOn()

reader = vtk.vtkJPEGReader()
reader.SetFileName("PythonIng_textur.jpg")

texture = vtk.vtkTexture()
texture.SetInputConnection(reader.GetOutputPort()) 

mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(texture_coords.GetOutputPort())

actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.SetTexture(texture)

renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(renderWindow)

renderer.AddActor(actor)

for i in range(360):
    actor.RotateZ(1)
    actor.RotateY(.5)
    renderWindow.Render()
    time.sleep(0.01)

interactor.Start()

Nun aber genug von VTK und der Erstellung von Grafiken, weiter geht es mit mathematischeren Themen.

Vektoren und Matrizen

[Bearbeiten]

Zahlenfolgen

[Bearbeiten]

Für das Erstellen von Zahlenfolgen bieten sich die Funktionen arange und linspace aus dem numpy-Modul an.

from numpy import *

start = 0
stop = 10
step = 2
num = 10

r = arange(start, stop, step)   # step ... Schrittweite
l = linspace(start, stop, num)  # num ... Anzahl der Werte

print("r = ", r)
print("l = ", l)

Ausgabe:

r =  [0 2 4 6 8]
l =  [ 0.          1.11111111  2.22222222  3.33333333  4.44444444  5.55555556
  6.66666667  7.77777778  8.88888889 10.        ]

Bei arange ist der stop-Wert nicht im Ergebnis enthalten, bei linspace aber sehr wohl.

Vektoren

[Bearbeiten]

Vektoren sollten jedem aus der Linearen Algebra bekannt sein.

Arrays

[Bearbeiten]

In Python mit NumPy kann man Vektoren durch die Funktion array erzeugen.

import numpy as np

l1 = (-5, 3, 2)
l2 = (1, 1, 4)

a1 = np.array(l1)
a2 = np.array(l2)

a3 = a1 + a2
a4 = 2 * a2

print(a1)
print(a2)
print(a3)
print(a3[2])
print(a4)

Ausgabe:

[-5  3  2]
[1 1 4]
[-4  4  6]
6
[2 2 8]

Zeilen- und Spaltenvektoren

[Bearbeiten]
import numpy as np

# Zeilenvektor
z = np.array([ [-5, 3, 2] ])
# Spaltenvektor
s = np.array([[1], [1], [4]])

print(z)
print(s)

Ausgabe:

[ [-5  3  2] ]
[[1]
 [1]
 [4]]

Skalarprodukt

[Bearbeiten]
import numpy as np

a1 = np.array((-5, 3, 2))
a2 = np.array((1, 1, 4))

skalarprodukt = np.dot(a1, a2)  

print(skalarprodukt)

Ausgabe:

6

Vektorprodukt

[Bearbeiten]

Python-Code:

import numpy as np

a1 = np.array((-5, 3, 2))
a2 = np.array((1, 1, 4)) 

vektorprodukt = np.cross(a1, a2) 

print(vektorprodukt)

Ausgabe:

[10 22 -8]

Transponierter Vektor

[Bearbeiten]
import numpy as np

# Zeilenvektor
z = np.array([ [-5, 3, 2] ])
# Spaltenvektor
s = np.array([[1], [1], [4]])

# transponierter Vektor
z_tp = np.transpose(z)
# transponierter Vektor
s_tp = np.transpose(s)

print(z_tp)
print(s_tp)

Ausgabe:

[[-5]
 [ 3]
 [ 2]]
[ [1 1 4] ]

Vektorfelder visualisieren

[Bearbeiten]
import matplotlib.pyplot as plt
import numpy as np

# Daten generieren
x = np.arange(0, 10, 1)
y = np.arange(0, 10, 1)
X, Y = np.meshgrid(x, y)
U = X * Y
V = Y + X

# Plotten
fig, ax = plt.subplots()

ax.quiver(X, Y, U, V, angles='xy')

plt.show()

Ausgabe:

Matrizen

[Bearbeiten]
import numpy as np
m1 = np.matrix([[1, 2, 3], [4, 5, 6]])
print(m1)

Ausgabe:

[[1 2 3]
 [4 5 6]]

Zugriff auf Matrizenelemente

[Bearbeiten]
import numpy as np

m1 = np.matrix([[1, 2, 3], [4, 5, 6]])

# Element aus Zeile 2 und Spalte 3 (Achtung! Index startet bei Null)
print(m1[1,2])

Ausgabe:

6

Addition und Subtraktion von Matrizen

[Bearbeiten]
import numpy as np

m1 = np.matrix([[1, 2, 3], [4, 5, 6]])
m2 = np.matrix([[0, 0, 2], [1, 3, 2]])

print(m1 + m2)
print(m1 - m2)

Ausgabe:

[[1 2 5]
 [5 8 8]]
[[1 2 1]
 [3 2 4]]

Transponierte Matrix

[Bearbeiten]
import numpy as np

m = np.matrix([[1, 2, 3], [4, 5, 6]])
mt = np.transpose(m) 

print(m)
print(mt)

Ausgabe:

[[1 2 3]
 [4 5 6]]
[[1 4]
 [2 5]
 [3 6]]

Rang einer Matrix

[Bearbeiten]
import numpy as np

m = np.matrix([[1, 3],  [0, -5]])
rg = np.linalg.matrix_rank(m)

print(rg)

Ausgabe:

2

Inverse Matrix

[Bearbeiten]
import numpy as np

m = np.matrix([[1, 3],  [0, -5]])
mi = np.linalg.inv(m)

print(mi)

Ausgabe:

[[ 1.   0.6]
 [-0.  -0.2]]

Multiplikation von Matrizen (falksches Schema)

[Bearbeiten]
import numpy as np

m1 = np.matrix([[1, 3, 4],  [0, -5, 1]])
m2 = np.matrix([[1, 2], [2, 3], [0, 2]])

print(m1 @ m2)

Ausgabe:

[[  7  19]
 [-10 -13]]

Eigenwerte und Eigenvektoren

[Bearbeiten]
import numpy as np

m = np.matrix([[5, 8],  [1, 3]])
D,V = np.linalg.eig(m)

# Eigenwerte
print(D)
# Eigenvektoren
print(V)

Ausgabe:

[7. 1.]
[[ 0.9701425  -0.89442719]
 [ 0.24253563  0.4472136 ]]

Teilmatrizen

[Bearbeiten]
import numpy as np
m = np.matrix([[1, 3, 4],  [0, -5, 1]])
print("m = ", m)

# Erste Zeile extrahieren
m1 = m[0,:]
print("m1 = ", m1)

# Das Element aus der 1. Zeile und der 2. Spalte extrahieren
m2 = m[0,1]
print("m2 = ", m2)

# Zweite Spalte extrahieren
m3 = m[:, 1]
print("m3 = ", m3)

Ausgabe:

m =  [[ 1  3  4]
 [ 0 -5  1]]
m1 =  [ [1 3 4] ]
m2 =  3
m3 =  [[ 3]
 [-5]]

Spezielle Matrizen

[Bearbeiten]

Nullmatrix

[Bearbeiten]
import numpy as np
z = np.zeros((3, 2))
print(z)

Ausgabe:

[[0. 0.]
 [0. 0.]
 [0. 0.]]

Einheitsmatrix

[Bearbeiten]
import numpy as np
z = np.eye(3)
print(z)

Ausgabe:

[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

Matrix mit lauter Einsen

[Bearbeiten]
import numpy as np
z = np.ones((3, 2))
print(z)

Ausgabe:

[[1. 1.]
 [1. 1.]
 [1. 1.]]

Spärlich besetzte Matrizen

[Bearbeiten]

Das Thema spärlich besetzter Matrizen wird hier nur kurz angerissen. Nähere Details siehe unter dem Weblink [19].

import numpy as np
import scipy

A = scipy.sparse.csr_array(np.eye(5))

print(A)

Ausgabe:

 (0, 0)        1.0
 (1, 1)        1.0
 (2, 2)        1.0
 (3, 3)        1.0
 (4, 4)        1.0

Lineare Gleichungssysteme

[Bearbeiten]

Sei ein lineares Gleichungssystem. sei die Koeffizientenmatrix, der Lösungsvektor und ein bekannter Vektor.

Beispiel:

import numpy as np

A = np.array([[5, 1], [0, 2]])
b = np.array([1, 2])

x = np.linalg.solve(A, b)

print(x)

Ausgabe:

[0. 1.]

Aufgabe

[Bearbeiten]
  • Lösen Sie folgendes Gleichungssystem mittels Python (und zur Kontrolle auch händisch):
5x + 6y - 2z = 12
3x - y  - 3z = 6
2x + 2y + 4z = 5

Polynome

[Bearbeiten]

Ein erstes einfaches Beispiel

[Bearbeiten]

Gegeben sei das Polynom . In Python:

import numpy as np

p = np.poly1d([7, 5, 0, 1])
print(p)

Ausgabe:

   3     2
7 x + 5 x + 1

Einzelne Polynomwerte berechnen

[Bearbeiten]
import numpy as np

p = np.poly1d([7, 5, 0, 1])
print(p(1.5))

Ausgabe:

35.875

Polynome integrieren und differenzieren

[Bearbeiten]
import numpy as np

p = np.poly1d([7, 5, 0, 1])

# 1. Ableitung
p1 = p.deriv()
p2 = p.deriv(1)

# 2. Ableitung
p3 = p.deriv(2)

# Integral
p4 = p.integ()

print(p1)
print(p2)
print(p3)
print(p4)

Ausgabe:

    2
21 x + 10 x
    2
21 x + 10 x

42 x + 10
      4         3
1.75 x + 1.667 x + 1 x

Nullstellen bestimmen

[Bearbeiten]
import numpy as np

p = np.poly1d([2, 5, 0, 4])
r = np.roots(p)

print(r)

Ausgabe:

[-2.7621427 +0.j          0.13107135+0.84077099j  0.13107135-0.84077099j]

Aufgaben

[Bearbeiten]
  • Berechnen Sie den Wert für x = 3 des Polynoms .
  • Differenzieren und integrieren Sie das Polynom .
  • Berechnen Sie die Nullstellen von .

Nichtlineare Gleichungen und Gleichungssysteme

[Bearbeiten]

Nullstellenbestimmung

[Bearbeiten]

Löse eine beliebige Gleichung f(x) = 0, z.B. :

import scipy
import numpy as np

def f(x):
    return x**2 - 5*np.cos(x) - 10
   
xstart = [-1, 1]        # Startwerte
xn = scipy.optimize.root(f, xstart)

print(xn.x)

Ausgabe:

[-2.46813009  2.46813009]

Funktionsgraph:

Gleichungssysteme

[Bearbeiten]

SymPy ist ein externes Modul, das symbolisches Rechnen (Symbolic Python) ermöglicht.

Folgende Aufgabe ist dem Buch "Knorrenschild: Numerische Mathematik, Hanser, 2017, Seite 72" entnommen. Zu lösen ist das nichtlineare Gleichungssystem

Mit Python ist das so möglich:

import sympy

x1, x2 = sympy.symbols("x1 x2") 

f1 = 2*x1 + 4*x2
f2 = 4*x1 + 8*x2**3

s = sympy.solve((f1, f2), x1, x2) 

print(s)

Ausgabe:

[(-2, 1), (0, 0), (2, -1)]

Plot:

Komplexe Zahlen

[Bearbeiten]

Die imaginäre Einheit wird in Python durch den Buchstaben j symbolisiert. Darstellen kann man eine komplexe Zahl bekannterweise in mehreren Formen:

  • Kartesische Darstellung
  • Polardarstellungen

Die konjugiert komplexe Zahl ist

Nachfolgend einige mathematische Operationen mit Python und NumPy.

import numpy as np

z1 = 2 + 5j           # kartesische Darstellung
z2 = 3 * np.exp(3j)   # Polardarstellung
 
# Addition
res = z1 + z2
print("z1 + z2 = ", res)

# Multiplikation
res = z1 * z2
print("z1 * z2 = ", res)

# Realteil
res = np.real(z2)
print("Realteil von z2 = ", res)

# Imaginärteil
res = np.imag(z2)
print("Imaginaerteil von z2 = ", res)

# Betrag
res = np.abs(z1)
print("Betrag von z1 = ", res)

# Argument
res = np.angle(z1)
print("Argument von z1 = ", res)

# Konjugiert komplexe Zahl
res = np.conj(z1)
print("Konjugiert komplexe Zahl von z1 = ", res)

Ausgabe:

z1 + z2 =  (-0.9699774898013365+5.423360024179601j)
z1 * z2 =  (-8.05675510050068-14.003167400647481j)
Realteil von z2 =  -2.9699774898013365
Imaginaerteil von z2 =  0.4233600241796016
Betrag von z1 =  5.385164807134504
Argument von z1 =  1.1902899496825317
Konjugiert komplexe Zahl von z1 =  (2-5j)

Interpolation

[Bearbeiten]
import numpy as np
import scipy
import matplotlib.pyplot as plt

# Stützpunkte
xp = np.arange(1, 6)
yp = (0, -5, 2, 7, 6)

ti = np.arange(1, 5, 0.01)

i1 = scipy.interpolate.interp1d(xp, yp, kind = "linear")
i2 = scipy.interpolate.interp1d(xp, yp, kind = "cubic") 

plt.plot(xp, yp, "rx")
plt.plot(xp, i1(xp))
plt.plot(ti, i2(ti))
plt.show()

Ausgabe:

Differenzialrechnung

[Bearbeiten]

Numerisches Differenzieren

[Bearbeiten]

Als Beispiel differenzieren wir und stellen das Ganze grafisch dar.

from findiff import Diff
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 1000)
f = 5 * x * np.sin(x)
dx = x[1] - x[0]

# Ableitung
d_dx = Diff(0, dx)
df_dx = d_dx(f)

# Grafik
plt.plot(x, f, label = "y")
plt.plot(x, df_dx, label = "y'")
plt.grid()
plt.legend(loc="best")

plt.show()

Ausgabe:

findiff ist ein externes Modul. Dieses muss installiert werden (z.B. so: ...\Python\Scripts\pip.exe install --upgrade findiff). Für die Vorgehensweise unter openSUSE Tumbleweed siehe das Kapitel VPython, nur dass das Ganze mit einer aktuelleren Python-Version exekutiert wird, z.B. mit Python 3.13. Das im Buch "Steinkamp: Der Python-Kurs für Ingenieure und Naturwissenschaftler, Rheinwerk" verwendete Modul "scipy.misc" ist veraltet (deprecated ... missbilligt). Lt. SciPy-Dokumentation für die Version 1.17.0 wurden alle entsprechenden Features schon entfernt.

Symbolisches Differenzieren

[Bearbeiten]

Differenzieren Sie die Funktionen und .

import sympy

x = sympy.symbols("x")

f1 = x**2;
f2 = sympy.sin(x) * sympy.cos(x/2.)   

d1 = sympy.diff(f1, x)
d2 = sympy.diff(f2, x)

print(d1)
print(d2)

Ausgabe:

2*x
-0.5*sin(0.5*x)*sin(x) + cos(0.5*x)*cos(x)

Aufgaben

[Bearbeiten]
  • Differenzieren Sie die Funktion und stellen Sie y, sowie y' grafisch am Bildschirm dar.
  • Differenzieren Sie die Funktion und stellen Sie y, sowie y' grafisch am Bildschirm dar.

Integralrechnung

[Bearbeiten]

Numerisches Integrieren

[Bearbeiten]

Berechnen Sie das Integral .

import scipy

def f(x):
    return x**2
   
i = scipy.integrate.quad(f, 0, 3)
print(i)

Ausgabe:

(9.000000000000002, 9.992007221626411e-14)

Das trifft den exakten Wert 9.0 ziemlich genau.

Berechnen Sie das Integral .

import scipy
import numpy as np

def f(x):
    return 2**(-x)
  
i = scipy.integrate.quad(f, 0, np.inf)
print(i)

Ausgabe:

(1.4426950408889556, 4.486558477977586e-09)

Symbolisches Integrieren

[Bearbeiten]

Berechnen Sie und .

import sympy

x = sympy.symbols("x")

f1 = x**2
f2 = sympy.sin(x) * sympy.cos(x/2.)   

i1 = sympy.integrate(f1, x)
i2 = sympy.integrate(f2, x)

print(i1)
print(i2)

Ausgabe:

x**3/3
-0.666666666666667*sin(0.5*x)*sin(x) - 1.33333333333333*cos(0.5*x)*cos(x)

Berechnen Sie das Integral .

import sympy

x = sympy.symbols("x")

f = 2**(-x)
i = sympy.integrate(f, (x, 0, sympy.oo))
print(i)

Ausgabe:

1/log(2)

sympy.oo steht für das  Unendlichzeichen (die liegende Acht oder das Möbiusband). Mit sympy.pprint(i) ließe sich letzere Ausgabe etwas schöner schreiben:

  1   
──────
log(2)

Man beachtete, log steht hier für den natürlichen Logarithmus ln.

Aufgaben

[Bearbeiten]
  • Integrieren Sie die Funktion von 1 bis 5.
  • Integrieren Sie die Funktion von 0 bis 4.
  • Integrieren Sie symbolisch.

Gewöhnliche Differenzialgleichungen

[Bearbeiten]

DGL numerisch lösen

[Bearbeiten]

Für die Lösung von Differenzialgleichungen steht u.a. die Funktion scipy.integrate.solve_ivp() zur Verfügung. Diese Funktion implementiert auch das Runge-Kutta-Verfahren (RK45).

Wikipedia hat einen Artikel zum Thema:


Beispiel :

import scipy
import numpy as np
import matplotlib.pyplot as plt

def dy_dx(x, y):
    return x**2 + y**3

y0 = [1]
xi = [0, 1]
x = np.arange(0, 1, 0.01)

z = scipy.integrate.solve_ivp(dy_dx, xi, y0, method="RK45", dense_output=True)
y = z.sol(x)

plt.plot(x, y.T)
plt.grid()
plt.show()

DGL symbolisch lösen

[Bearbeiten]

Beispiel :

import sympy

x = sympy.symbols("x")
y = sympy.Function("f")(x)

dgl = x**2 + y**3 

lsg = sympy.dsolve(dgl, y)

print(lsg)

Ausgabe:

[Eq(f(x), (-x**2)**(1/3)), Eq(f(x), (-x**2)**(1/3)*(-1 - sqrt(3)*I)/2), Eq(f(x), (-x**2)**(1/3)*(-1 + sqrt(3)*I)/2)]

Mit sympy.pprint (pretty print) lässt sich die Ausgabe etwas übersichtlicher darstellen.

import sympy

x = sympy.symbols("x")
y = sympy.Function("f")(x)

dgl = x**2 + y**3 

lsg = sympy.dsolve(dgl, y)

sympy.pprint(lsg)

Ausgabe:

⎡                           _____                        _____            ⎤
⎢          _____         3 ╱   2                      3 ╱   2             ⎥
⎢       3 ╱   2          ╲╱  -x  ⋅(-1 - √3⋅ⅈ)         ╲╱  -x  ⋅(-1 + √3⋅ⅈ)⎥
⎢f(x) = ╲╱  -x  , f(x) = ────────────────────, f(x) = ────────────────────⎥
⎣                                 2                            2          ⎦

Aufgaben

[Bearbeiten]
  • Lösen Sie die Differenzialgleichung mit Python. Kontrollieren Sie das Ergebnis, indem Sie die DGl händisch lösen.
  • Lösen Sie die Differenzialgleichung . Kontrollieren Sie das Ergebnis, indem Sie die DGl händisch lösen.
  • Lösen Sie die Differenzialgleichung .

Laplace-Transformation

[Bearbeiten]

Laplace-Transformation:

Inverse Laplace-Transformation:

Siehe auch Ing_Mathematik:_Laplace-Transformation

Code:

import sympy
from sympy.abc import t, s

# Laplace-Transformation der Funktion f(t) = 1 (Heaviside-Fkt.)
f = 1
# alternativ: f = sympy.Heaviside(t)
F = sympy.laplace_transform(f, t, s, noconds=True)
print("Laplace-Transformierte F(s):", F) 

# Inverse Laplace-Transformation zurück in den Zeitbereich
f_inv = sympy.inverse_laplace_transform(F, s, t)
print("Inverse Transformation f(t):", f_inv)

Ausgabe:

Laplace-Transformierte F(s): 1/s
Inverse Transformation f(t): Heaviside(t)

Die Zeile

from sympy.abc import t, s

steht alternativ für

t = sympy.symbols("t")
s = sympy.symbols("s")

Fourier-Reihen

[Bearbeiten]

Für die Sägezahnfunktion sei die Fourierreihe mit einem Python-Programm (unter Mithilfe von sympy) hergeleitet.

Code:

from sympy import fourier_series, pi, symbols, pprint

x = symbols('x')
f = x
s = fourier_series(f, (x, 0, 2*pi))
pprint(s.truncate(n=4))

Ausgabe:

                       2⋅sin(3⋅x)    
-2⋅sin(x) - sin(2⋅x) - ────────── + π
                           3

Siehe auch Ing Mathematik: Fourierreihen.

Ein komplizierteres Beispiel:

Code:

import sympy as sp

H = sp.Symbol('H', positive=True)
T = sp.Symbol('T', positive=True)
t = sp.Symbol('t')


f = sp.Piecewise(
    (H, (t > 0) & (t < T/2)),
    (2*H/T*(t-T/2), (t > T/2) & (t < T))
)

f_series = sp.fourier_series(f, (t, 0, T))
sp.pprint(f_series.truncate(4))

Ausgabe:

     ⎛2⋅π⋅t⎞        ⎛4⋅π⋅t⎞        ⎛6⋅π⋅t⎞          ⎛2⋅π⋅t⎞          ⎛6⋅π⋅t⎞      
H⋅sin⎜─────⎟   H⋅sin⎜─────⎟   H⋅sin⎜─────⎟   2⋅H⋅cos⎜─────⎟   2⋅H⋅cos⎜─────⎟      
     ⎝  T  ⎠        ⎝  T  ⎠        ⎝  T  ⎠          ⎝  T  ⎠          ⎝  T  ⎠   3⋅H
──────────── - ──────────── + ──────────── + ────────────── + ────────────── + ───
     π             2⋅π            3⋅π               2                 2         4 
                                                   π               9⋅π

Rechnen mit wirklich großen Zahlen

[Bearbeiten]

Bekannt ist, dass Python kaum Einschränkungen beim Wertebereich von Ganzzahlen hat, z.B.

print(10**300)

Ausgabe (gekürzt):

100000000000000000000...00000000000000000000000000000000000000000000000000000000000000000000000

Ähnliches geht auch mit Gleitpunktzahlen, z.B. durch die Verwendung des Moduls mpmath:

import mpmath
print(mpmath.mpf(1500.4)**mpmath.mpf(300))

Ausgabe:

7.27975299218612e+952

Anderes Beispiel:

from mpmath import mp, pi
mp.dps = 100
print(pi)

Ausgabe:

3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068

mpmath kann noch einiges mehr, dazu sei aber auf die entsprechende Dokumentation auf der mpmath-Homepage verwiesen. mpmath ist Bestandteil von SymPy, kann aber auch separat installiert werden.

Aber auch Python selbst besitzt eine Möglichkeit, um mit großen bzw. exakten Gleitpunktzahlen zu rechnen, nämlich das interne Modul decimal. Dieses hat einige Vorteile gegenüber mpmath, aber auch gravierende Nachteile. Diese seien hier nicht detailliert aufgezählt. Grob gesagt hat decimal im Finanzwesen seine Berechtigung. Für wissenschaftliche Anwendungen wird aber mpmath vorzuziehen sein, da es u.a. vielfältige mathematische Funktionen bereit stellt. Nachfolgend ein einfaches Beispiel mit decimal:

import decimal
print("Potenzierung:", decimal.Decimal(1500.4) ** decimal.Decimal(300.0))
print("Einfache Addition:", 0.1 + 0.2)
decimal.getcontext().prec = 50
print("Addition mit decimal:", decimal.Decimal("0.1") + decimal.Decimal("0.2"))

Ausgabe:

Potenzierung: 7.279752992186121551039839134E+952
Einfache Addition: 0.30000000000000004
Addition mit decimal: 0.3

Aufgabe: Recherchieren Sie im Internet die genauen Vor- und Nachteile von decimal und mpmath. Verwenden Sie dazu auch KI (z.B. von Google, chatgpt).

Regelungstechnische Aufgabenstellungen

[Bearbeiten]

Für regelungstechnische Aufgaben gibt es u.a. das externe Paket control. Hier soll nicht detailliert darauf eingegangen werden. Anhand eines Beispiels soll anschließend nur die Visualisierung in Form eines Bode-Diagramms und der Sprungantwort gezeigt werden. Gegeben sei ein P-Regler mit und eine Strecke . Gesucht sei vorerst ein Bode-Diagramm für den offenen Regelkreis und das Führungsverhalten.

import numpy as np
import control as ct
import matplotlib.pyplot as plt

zaehler1 = np.array([1.])
nenner1  = np.array([30., 20., 10., 1.5])
strecke  = ct.tf(zaehler1, nenner1)

zaehler2 = np.array([5.])
nenner2  = np.array([2.])
regler   = ct.tf(zaehler2, nenner2)

G0 = regler*strecke  # oder: G0 = ct.series(regler, strecke)
Gw = ct.feedback(G0)

ct.bode_plot(G0, label='G0')
ct.bode_plot(Gw, label='Gw')
plt.show()

Nun noch für obiges Beispiel die Sprungantwort. Diese zeigt einige große Überschwinger, d.h. der Regler kann sicher noch optimiert werden.

import numpy as np
import control as ct
import matplotlib.pyplot as plt

zaehler1 = np.array([1.])
nenner1  = np.array([30., 20., 10., 1.5])
strecke  = ct.tf(zaehler1, nenner1)

zaehler2 = np.array([5.])
nenner2  = np.array([2.])
regler   = ct.tf(zaehler2, nenner2)

G0 = regler*strecke 
Gw = ct.feedback(G0) 

t, y = ct.step_response(Gw)

plt.plot(t,y)
plt.title('Sprungantwort')
plt.xlabel('t')
plt.ylabel('h(t)')
plt.grid()
plt.show()

Einige weitere wichtige Daten (Phasenreserve, Amplitudenreserve, Durchtrittsfrequenz) lassen sich mittels der control-Funktion margin() ermitteln. Die Ortskurve lässt sich mit der Funktion nyquist_plot() zeichnen. Dies sei hier aber nicht weiter ausgeführt.

Aufgaben

[Bearbeiten]
  • Zeichen Sie mit Python die Ortskurve für obiges Beispiel.
  • Was passiert, wenn man die Reglerverstärkung weiter aufdreht (z.B. auf )?
  • Wie sehen das Bode-Diagramm und die Sprungantwort aus, wenn ein PI-Regler verwendet wird?

Stereostatik etc.

[Bearbeiten]

Das Modul SymPy bietet einige Möglichkeiten einfache Bauwerke zu berechnen, z.B. Balken oder Fachwerke. Nachfolgend wird ein einfaches Fachwerk berechnet und gezeichnet.

Python-Code:

from sympy.physics.continuum_mechanics.truss import Truss 

t = Truss()
# Knoten
t.add_node(("A", -3, 0), ("B", 0, 0), ("C", 4, 0), ("D", 7, 0),
           ("E", 6, 1.5), ("F", 2, 3), ("G", -2, 1.5))
# Stäbe
t.add_member(("AB","A","B"), ("BC","B","C"), ("CD","C","D"))
t.add_member(("AG","A","G"), ("GB","G","B"), ("GF","G","F"))
t.add_member(("BF","B","F"), ("FC","F","C"), ("CE","C","E"))
t.add_member(("FE","F","E"), ("DE","D","E"))
# Auflager; roller ... Loslager, pinned ... Festlager
t.apply_support(("A","roller"), ("D","pinned"))
# Einwirkende Kräfte
t.apply_load(("G", 5, 270), ("E", 3, 90))

# Berechnung 
t.solve()
print("Reaction Forces: ", t.reaction_loads)
print("Internal Forces: ", t.internal_forces)

# Fachwerk zeichnen
p = t.draw()
p.show()

Ausgabe auf der Konsole:

Reaction Forces:  {'R_A_y': 4.20000000000000, 'R_D_x': 0, 'R_D_y': -2.20000000000000}
Internal Forces:  {'AB': 2.80000000000000, 'BC': 0.333333333333333, 'CD': -1.46666666666667, 
'AG': -5.04777178564958, 'GB': -2.05555555555556, 'GF': -1.23413387432364, 
'BF': 0.411111111111111*sqrt(13), 'FC': -0.3*sqrt(13), 'CE': 1.50000000000000, 
'FE': 0.284800124843917, 'DE': 2.64407093534026}

Zeichnung:

Details zu diesem Thema siehe z.B. Continuum Mechanics oder Continuum Mechanics Tutorials. Auch andere mechanische Probleme werden von SymPy abgehandelt (Physics Tutorials).

Aufgabe

[Bearbeiten]

Gegeben sei ein einseitig eingespannter Kragträger. Belastet wird er durch eine Einzellast am Trägerende. Für die Daten siehe folgende ASCII-Skizze:

                           | 20 kN  
   //|---> x               |
   //|                     V
   //|----------------------
   //|         10 m        |

Elastizitätsmodul E = 2,1*10⁵ N/mm²
Flächenträgheitsmoment I = 0.001 m⁴

Berechnen Sie die Auflagerreaktionen, den Querkraft- und Biegemomentenverlauf, sowie die Verformungen. Stellen Sie dies mit Hilfe von SymPy graphisch und auch mittels Formeln dar. Verwenden Sie dazu auch pprint (pretty print) aus dem SymPy-Modul. Zwecks Lösungsansatz siehe die oben aufgeführte Seite "Continuum Mechanics Tutorials". Achten Sie auch auf die Einheiten! Kontrollieren Sie das Ganze mittels händischer Rechnung. In dem genannten Tutorial ist von "Singularity Functions" die Rede. Gemeint ist damit in diesem Kontext die  Föppl-Klammer.

Einige Python-Programme, vorrangig zu Maschinenelementen, finden sich auf BayMP für Python (Balken, Zahnräder, Stabknickung usw.).

Thermodynamik

[Bearbeiten]

PYroMat

[Bearbeiten]

Für thermodynamische Aufgabenstellungen gibt es verschiedene externe Module. Eines davon ist PYroMat (siehe auch [20]). Damit lassen sich thermodynamische Stoffdaten für viele Substanzen berechnen.

Beispiel (einige Stoffdaten für Wasser bei 400°C und 20 bar berechnen):

import pyromat as pm

# Wasserdaten laden:
H2O = pm.get('mp.H2O')

# Stoffdaten berechnen:
T = 673.15  # Temperatur in Kelvin
p = 20      # Druck in bar
v = H2O.v(T, p)
h = H2O.h(T, p)
s = H2O.s(T, p)
print(f"Spezifisches Volumen: {v} m³/kg")
print(f"Spezifische Enthalpie: {h} kJ/kg")
print(f"Spezifische Entropie: {s} kJ/(kg K)")

Ausgabe:

Spezifisches Volumen: [0.1512163] m³/kg
Spezifische Enthalpie: [3248.3789473] kJ/kg
Spezifische Entropie: [7.12924142] kJ/(kg K)

PYroMat muss vorab installiert werden (z.B. mittels pip, in eine virtuelle Umgebung)

mp steht für "multi phase". Für ein ideales Gas wäre ig zuständig, z.B. 'ig.O2'.

Beispiel (T-s-Diagramm für Wasser zeichnen):

import numpy as np
import matplotlib.pyplot as plt
import pyromat as pm

# Konfigurieren
pm.config["unit_pressure"] = "bar"
pm.config["unit_temperature"] = "K"
fluid = pm.get("mp.H2O")

# Temperaturbereich für das Nassdampfgebiet
T_tripel = 273.16
T_crit = 647.096
T = np.linspace(T_tripel, T_crit - 0.1, 200)

# Sättigungslinien berechnen und zeichnen
for x in np.linspace(0.0, 1.0, 5):
    s = fluid.s(T=T, x=x)
    if(x<=0.0):
        plt.plot(s, T, label="Siedelinie x=%3.1f" % x, linewidth=2.0)
    elif(x>=1.0):
        plt.plot(s, T, label="Taulinie x=%3.1f" % x, linewidth=2.0)
    else:
        plt.plot(s, T, label="x=%3.1f" % x, linewidth=1.0)

# Isobaren zeichnen
p_values = [0.1, 1, 10, 50, 100]
T_isobar = np.linspace(T_tripel, 1000, 200)
t = 0.7

for p in p_values:
    s_iso = fluid.s(T=T_isobar, p=p)
    plt.plot(s_iso, T_isobar, 'k-', alpha=0.8, linewidth=0.8)

    t += .05
    idx = int(len(s_iso) * t)
    plt.text(s_iso[idx], T_isobar[idx], f"{p} bar", fontsize=9, alpha=0.8)

# Diagramm zeichnen
plt.title("T-s-Diagramm für Wasser")
plt.xlabel("Spezifische Entropie s in kJ/kg K", fontsize=10)
plt.ylabel("Temperatur T in K", fontsize=10)
plt.legend(loc="best")
plt.grid(True)
plt.show()

Ausgabe (in etwa so):

CoolProp

[Bearbeiten]

Auch mit CoolProp können Stoffdaten berechnet werden. Siehe auch [21]

Beispiel (Wasser bei 20bar und 400°C):

import CoolProp.CoolProp as CP

fluid = 'Water'
T = 673.15   # Temperatur in Kelvin
P = 20e5     # Druck in Pascal

dichte = CP.PropsSI('D', 'T', T, 'P', P, fluid)
enthalpie = CP.PropsSI('H', 'T', T, 'P', P, fluid)
entropie = CP.PropsSI('S', 'T', T, 'P', P, fluid)

print(f"Spez. Volumen: {1/dichte:.6f} m³/kg")
print(f"Spez. Enthalpie: {enthalpie:.2f} J/kg")
print(f"Spez. Entropie: {entropie:.2f} J/kgK")

Ausgabe:

Spez. Volumen: 0.151215 m³/kg
Spez. Enthalpie: 3248344.02 J/kg
Spez. Entropie: 7129.16 J/kgK

iapws

[Bearbeiten]

Um Werte für Wasser(dampf) zu erhalten (IAPWS; International Association for the Properties of Water and Steam) gibt es die Bibliothek iapws. Siehe auch [22] und [23]

Beispiel (Wasser für 20bar und 400°C):

from iapws import IAPWS97

dampf = IAPWS97(P=2.0, T=673.15)

print(f"Spezifisches Volumen: {dampf.v:.6f} m³/kg")
print(f"Spezifische Enthalpie: {dampf.h:.2f} kJ/kg")
print(f"Spezifische Entropie: {dampf.s:.4f} kJ/(kgK)")
print(f"Phase: {dampf.phase}")

Ausgabe:

Spezifisches Volumen: 0.151208 m³/kg
Spezifische Enthalpie: 3248.23 kJ/kg
Spezifische Entropie: 7.1290 kJ/(kgK)
Phase: Gas

TESPy

[Bearbeiten]

Ein anderes Modul für einen anderen Aufgabenzweck ist TESPy (Thermal Engineering Systems in Python). Dieses Modul ist für die Anlagensimulation zuständig. Für nähere Informationen siehe [24]. Als Beipiel sei hier vorerst Code, der von der Google KI generiert wurde, angeführt. Der Code wurde überarbeitet, damit keine Warnungen auftreten. Bitte aber den Code trotzdem mit Vorsicht genießen, auch KI-generierter Code kann Fehler aufweisen. Eine Pumpe wird berechnet:

from tespy.components import Sink, Source, Pump
from tespy.connections import Connection
from tespy.networks import Network

# 1. Netzwerk definieren (Zentrales Steuerungselement)
# Wir wählen Wasser als Fluid und bar/Celsius als Einheiten
nw = Network(fluids=["water"])
nw.units.set_defaults(pressure="bar", pressure_difference="bar", 
                      temperature="°C", enthalpy="kJ / kg")

# 2. Komponenten erstellen
eingang = Source("Wasserquelle")
ausgang = Sink("Wasserspeicher")
pumpe = Pump("Speisewasserpumpe")

# 3. Verbindungen definieren (Komponenten miteinander verknüpfen)
c1 = Connection(eingang, "out1", pumpe, "in1")
c2 = Connection(pumpe, "out1", ausgang, "in1")

# Verbindungen dem Netzwerk hinzufügen
nw.add_conns(c1, c2)

# 4. Randbedingungen und Parameter festlegen
# Zustand am Eingang (Druck, Temperatur, Massenstrom, Fluid-Zusammensetzung)
c1.set_attr(
    v=1,  # Massenstrom: 1 kg/s
    T=20,  # Temperatur: 20 °C
    p=1,  # Druck: 1 bar
    fluid={"water": 1},  # 100% Wasser
)

# Zustand am Ausgang / Zielwerte der Pumpe
c2.set_attr(p=10)  # Ziel-Druck nach der Pumpe: 10 bar

# Pumpeneigenschaften festlegen
pumpe.set_attr(eta_s=0.8)  # Isentroper Wirkungsgrad von 80%

# 5. Simulation ausführen
nw.solve(mode="design")

# 6. Ergebnisse ausgeben
nw.print_results()

# Spezifische Werte direkt auslesen
print("\n--- Auswertung ---")
print(f"Erforderliche Pumpenleistung: {pumpe.P.val / 1000:.2f} kW")
print(f"Temperatur nach der Pumpe: {c2.T.val:.2f} °C")

Ausgabe (gekürzt):

 iter  | residual   | progress   | massflow   | pressure   | enthalpy   | fluid      | component  
-------+------------+------------+------------+------------+------------+------------+------------
 1     | 7.04e+04   | 12 %       | 9.96e+02   | 0.00e+00   | 8.81e+04   | 0.00e+00   | 0.00e+00   
 2     | 5.91e-12   | 100 %      | 1.11e-13   | 0.00e+00   | 7.39e-12   | 0.00e+00   | 0.00e+00   
 3     | 5.80e-12   | 100 %      | 0.00e+00   | 0.00e+00   | 7.25e-12   | 0.00e+00   | 0.00e+00   
 4     | 5.80e-12   | 100 %      | 0.00e+00   | 0.00e+00   | 7.25e-12   | 0.00e+00   | 0.00e+00   
Total iterations: 4, Calculation time: 0.01 s, Iterations per second: 480.85

##### RESULTS (Pump) #####
+-------------------+----------+----------+-----------+----------+----------+----------+
|                   |        P |       pr |        dp |      eta |    eta_s |     head |
|-------------------+----------+----------+-----------+----------+----------+----------|
| Speisewasserpumpe | 1.12e+06 | 1.00e+01 | -9.00e+00 | 8.00e-01 | 8.00e-01 | 9.19e+01 |
+-------------------+----------+----------+-----------+----------+----------+----------+
...
...
--- Auswertung ---
Erforderliche Pumpenleistung: 1124.77 kW
Temperatur nach der Pumpe: 20.07 °C

Stochastik

[Bearbeiten]

Die  Stochastik ist ein sehr weites Feld. Hier werden etliche wichtige Themen kurz angerissen. Python stellt mit den Moduln math und statistics Software zu diesem Zwecke bereit. math und statistics sind bereits im Lieferumfang von Python enthalten. Aber auch mit den externen Modulen NumPy, SciPy, stochastic und pandas kann man Stochastik in Python betreiben. Die Theorie der Wahrscheinlichkeitsrechnung und Statistik soll etwas später in Band 5 dieser Buchreihe behandelt werden.

Lageparameter

[Bearbeiten]
import statistics

werte = [1, 3, 4, 4, 1, 7, 9, 1, 2, 3]

m1 = statistics.mean(werte)
m2 = statistics.mode(werte)
m3 = statistics.median(werte)

print("Arithmetischer Mittelwert = ", m1)
print("Modalwert = ", m2)
print("Median = ", m3)

Ausgabe:

Arithmetischer Mittelwert =  3.5
Modalwert =  1
Median =  3.0

Streuungsparameter

[Bearbeiten]

Beispiel (Berechnung der Standardabweichung):

import statistics
werte = [1, 3, 4, 4, 1, 7, 9, 1, 2, 3]
s = statistics.stdev(werte)
print("Standardabweichung = ", s)

Ausgabe:

Standardabweichung =  2.6770630673681683

Beispiel (Berechnung des Variationskoeffizienten V = Standardabweichung/Mittelwert)

import numpy as np
from scipy import stats
import statistics

k = 50

dat1 = [14, 21, 18, 25, 30, 17, 20]
dat = np.array(dat1)

# Mit SciPy
v = stats.variation(dat)
vddof = stats.variation(dat, ddof=1)
print("V SciPy: ", v)
print("V DDOF SciPy: ", vddof)
print(k*"-")

# mit NumPy
mittelwert1 = np.mean(dat)
std_abw1 = np.std(dat)
std_abw1ddof = np.std(dat, ddof=1) 
v1= std_abw1 / mittelwert1
v1ddof = std_abw1ddof / mittelwert1
print("Mittelwert NumPy: ", mittelwert1)
print("Std.abw. NumPy: ", std_abw1)
print("Std.abw. DDOF NumPy: ", std_abw1ddof)
print("V NumPy: ", v1)
print("V DDOF NumPy: ", v1ddof)
print(k*"-")

# nur mit reinem Python
mittelwert2 = statistics.mean(dat1)
std_abw2 = statistics.stdev(dat1)
v2 = std_abw2 / mittelwert2
print("Mittelwert Python: ", mittelwert2)
print("Std.abw. Python: ", std_abw2)
print("V Python:", v2)
print(k*"-")

Ausgabe:

V SciPy:  0.23890355966467272
V DDOF SciPy:  0.25804533701889254
--------------------------------------------------
Mittelwert NumPy:  20.714285714285715
Std.abw. NumPy:  4.948716593053935
Std.abw. DDOF NumPy:  5.3452248382484875
V NumPy:  0.23890355966467272
V DDOF NumPy:  0.2580453370188925
--------------------------------------------------
Mittelwert Python:  20.714285714285715
Std.abw. Python:  5.3452248382484875
V Python: 0.2580453370188925
--------------------------------------------------

Der Unterschied bei der Standardabweichung zwischen reinem Python und den externen Bibliotheken SciPy und NumPy entsteht dadurch, dass einmal durch (n-1) und das andere Mal nur durch n dividiert wird. Dies kann bei NumPy und SciPy dadurch entschärft werden, indem ddof=1 gesetzt wird. ddof steht für Delta Degrees of Freedom.

Kombinatorik

[Bearbeiten]

Beispiel:

import math

n = 7
k = 5

print("n! = ", math.factorial(n))
print("Kombinationen (n über k) = ", math.comb(n, k))

Ausgabe:

n! =  5040
Kombinationen (n über k) =  21

Siehe zu diesem Thema auch Ing Mathematik: Permutationen, Kombinationen, binomischer Lehrsatz. Die Anzahlen lassen sich einfach aus den dortigen Formeln ermitteln, z.B. bei Permutationen mit oder Variationen mit Wiederholungen als . Will man die Kombinationen oder Variationen aber auch als Liste ausgeben, so kann das Modul itertools nützlich sein.

Beispiel (Variationen ohne Wiederholung):

from itertools import permutations

menge = ["A", "B", "C", "D"]  # n = 4
k = 3

variationen = list(permutations(menge, k))

for v in variationen:
    print("".join(v))

print(50*"-")
print(len(variationen))

Ausgabe (gekürzt):

ABC
ABD
ACB
...
DCA
DCB
--------------------------------------------------
24

Siehe zum Modul itertools auch die Website [25].

  • Variationen mit Wiederholung: itertools.product()
  • Kombinationen ohne Wiederholung: itertools.combinations()
  • Kombinationen mit Wiederholung: itertools.combinations_with_replacement()

Zufallszahlen

[Bearbeiten]

Beispiel:

import random

# Ganzzahlige Zufallszahl von 1 bis 10
zufallszahl1 = random.randint(1, 10)

# Gleitpunktzahlen
# zwischen 0.0 und 1.0
zufallszahl2 = random.random()
# Zahl zwischen 1.5 und 9.5
zufallszahl3 = random.uniform(1.5, 9.5)

# aus Liste auswählen
farbe = ["Rot", "Grün", "Blau"]
zufallswert = random.choice(farbe)

print(zufallszahl1)
print(zufallszahl2)
print(zufallszahl3)
print(zufallswert)

Ausgabe, z.B.:

5
0.14147945849015753
6.894003397570905
Rot

Benötigt man mehrere Zufallszahlen, so ist das Modul numpy zu bevorzugen, z.B.:

  • Normalverteilung: np.random.normal(...)
  • Gleichverteilung: np.random.uniform(...)

Histogramm

[Bearbeiten]

Zum Thema Histogramm siehe  Histogramm.

Beispiel (mit Matplotlib):

import matplotlib.pyplot as plt
import numpy as np

daten = np.random.normal(loc=50, scale=10, size=1000)

plt.hist(daten, bins=25, edgecolor='darkgray')
plt.show()

Ausgabe:

Beispiel (mit Seaborn):

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

daten = np.random.normal(loc=50, scale=10, size=1000)
sns.set_theme(style="darkgrid")
sns.histplot(data=daten)
plt.show()

Ausgabe:

Das Kürzel sns ist Konvention und steht für die fiktive Figur Samuel Norman Seaborn aus der US-Fernsehserie   The West Wing.

Box-Plot

[Bearbeiten]

Siehe auch  Box-Plot.

Beispiel (mit Seaborn erstellt):

import seaborn as sns
import matplotlib.pyplot as plt

df = sns.load_dataset("tips")
sns.boxplot(data=df, x="day", y="tip", hue="day", legend=False)
plt.show()

Ausgabe:

Beispiel (mit Matplotlib erstellt):

import matplotlib.pyplot as plt

daten = [12, 15, 18, 19, 22, 25, 28, 30, 31, 35, 42, 55, 12, 25]

plt.boxplot(daten, patch_artist=True)
plt.title("Boxplot mit Matplotlib")
plt.ylabel("Daten")
plt.show()

Ausgabe:

Um mehrere Box-Plots unterschiedlicher Farbe mit Matplotlib in einem Diagramm zu zeichnen, können Sie folgendermaßen vorgehen:

import matplotlib.pyplot as plt

daten = [[12, 15, 18, 19, 22, 25, 28, 30, 31, 35, 42, 55, 12, 25],
         [10, 19, 20, 21, 20, 30, 19, 40, 11, 17, 19, 21]]

farben = ["green", "blue"]

boxplot = plt.boxplot(daten, patch_artist=True)

for patch, farbe in zip(boxplot['boxes'], farben):
    patch.set_facecolor(farbe)

plt.title("Boxplot mit Matplotlib")
plt.ylabel("Daten")
plt.show()

Regressionsrechnung

[Bearbeiten]

Beispiel:

import numpy as np
import matplotlib.pyplot as plt

# Messpunkte
x = np.array([1, 3, 5, 6, 8, 10, 20])
y = np.array([3, 4, 5, 5, 7, 9, 11])

# Regressionskurve (Grad 1 = lineare Regression, 2 = Polynom-Regression 2. Gr.)
# y = kx + d
k, d = np.polyfit(x, y, deg=1)
# y = ax**2 + bx + c
a, b, c = np.polyfit(x, y, deg=2)

x_l = np.linspace(1, 20, 100)
y_p = a * x_l**2 + b * x_l + c

# Zeichnen
plt.scatter(x, y, color='green', label='Messpunkte')
plt.plot(x, k*x + d, color='blue', label='Regressionsgerade')
plt.plot(x_l, y_p, color='red', label='Regressionspolynom 2. Gr.')
plt.xlabel('x')
plt.ylabel('y')
plt.grid()
plt.axis("equal")
plt.legend(loc="best")
plt.show()

Ausgabe:

Korrelationsrechnung

[Bearbeiten]

Beispiel:

import pandas as pd
import matplotlib.pyplot as plt

# Messdaten
x = [1, 3, 4, 5, 6]
y = [2, 4, 6, 8, 5]

daten = {'X': x, 'Y': y}
df = pd.DataFrame(daten)

# Korrelation
korr = df['X'].corr(df['Y'])
print(f"Korrelationskoeff.: {korr}") 

# Messpunkte zeichnen
plt.scatter(x, y, color='green', label='Messpunkte')
plt.grid()
plt.axis("equal")
plt.legend(loc="best")
plt.show()

Ausgabe:

Korrelationskoeff.: 0.7556096518348252

Mengen und Venn-Diagramme

[Bearbeiten]

Beispiel:

import matplotlib.pyplot as plt
from matplotlib_venn import venn2

menge_a = {1, 2, 3, 4, 5, 6}
menge_b = {4, 5, 6, 7, 8}

vereinigung = menge_a | menge_b
schnitt = menge_a & menge_b
print("Vereinigungsmenge = ", vereinigung)
print("Schnittmenge = ", schnitt)

venn2([menge_a, menge_b], set_labels=('Menge A', 'Menge B'))
plt.show()

Ausgabe:

Vereinigungsmenge =  {1, 2, 3, 4, 5, 6, 7, 8}
Schnittmenge =  {4, 5, 6}

Siehe auch  Mengendiagramm#Venn-Diagramme.

Verteilungs- und Dichtefunktion

[Bearbeiten]
  • CDF ... Cumulative Distribution Function, Verteilungsfunktion
  • PDF ... Probability Density Function, Dichtefunktion

Beispiel (Normalverteilung):

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm

my, sigma = 0, 1
x = np.linspace(-4, 4, 50)

pdf = norm.pdf(x, my, sigma)
cdf = norm.cdf(x, my, sigma)

plt.plot(x, pdf, lw=2, label="Dichtefunktion")
plt.plot(x, cdf, lw=2, label="Verteilungsfunktion")
plt.legend()
plt.grid()
plt.show()

Ausgabe:

Beispiel (-Verteilung):

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats

x = np.linspace(0, 20, 500)

# df ... degree of freedom, Freiheitsgrad
pdf = (stats.chi2.pdf(x, df=2), stats.chi2.pdf(x, df=5), stats.chi2.pdf(x, df=10))

for i in range(0,3):
    if(i==0):
        lab = "Freiheitsgrad 2"
    elif(i==1):
        lab = "Freiheitsgrad 5"
    else:
        lab = "Freiheitsgrad 10"

    plt.plot(x, pdf[i], label=lab, lw=2)

plt.grid()
plt.legend()
plt.show()

Ausgabe:

Schätzen und Testen

[Bearbeiten]

Intervallschätzung

[Bearbeiten]

Als Beispiel seien Daten gegeben, die von Dürr, Mayer: Wahrscheinlichkeitsrechnung und Schließende Statistik; 7. Aufl., Hanser, 2014, Seite 137 stammen. Und zwar soll das 95%-Vertrauensintervall für den Mittelwert des Kaloriengehalts (kcal/100g) von Hähnchen ermittelt werden. Wir wollen das mit Python inkl. NumPy und SciPy durchführen. Die Stichprobe ist groß (50 Hähnchen):

Python-Code:

import numpy as np
import scipy.stats as stats

# Stichprobe
daten = [309, 202, 234, 252, 240, 225, 241, 212, 118, 191,
         236, 204, 213, 220, 219, 218, 195, 159, 195, 206,
         207, 232, 215, 210, 204, 332, 241, 225, 235, 193,
         238, 187, 189, 203, 190, 252, 227, 212, 180, 178,
         242, 236, 174, 240, 195, 223, 213, 209, 200, 203]

# Parameter definieren
konfidenzniveau = 0.95
mean = np.mean(daten)
std = np.std(daten, ddof=1)
stdfehler = stats.sem(daten)

intervall = stats.norm.interval(confidence=konfidenzniveau, loc=mean, scale=stdfehler)

print(f"Mittelwert: {mean}")
print(f"Standardabweichung: {std}")
print(f"Konfidenzintervall: {intervall}")

Ausgabe:

Mittelwert: 215.48
Standardabweichung: 33.14238915925757
Konfidenzintervall: (np.float64(206.29356722321992), np.float64(224.66643277678006))

Diese Werte stimmen gerundet mit denen im genannten Buch überein. Zum Code selbst:

  • sem steht für standard error of the mean.
  • scipy.stats.norm ... Modul für die Normalverteilung.

Punktschätzung

[Bearbeiten]

Gleiche Daten wie oben bei der Intervallschätzung.

Python-Code:

import numpy as np
from scipy import stats

daten = [309, 202, 234, 252, 240, 225, 241, 212, 118, 191,
         236, 204, 213, 220, 219, 218, 195, 159, 195, 206,
         207, 232, 215, 210, 204, 332, 241, 225, 235, 193,
         238, 187, 189, 203, 190, 252, 227, 212, 180, 178,
         242, 236, 174, 240, 195, 223, 213, 209, 200, 203
        ]

mu_hat, sigma_hat = stats.norm.fit(daten) 

print(f"Schätzer für den Erwartungswert (μ): {mu_hat:.4f}")
print(f"Schätzer für die Standardabweichung (σ): {sigma_hat:.4f}")

Ausgabe:

Schätzer für den Erwartungswert (μ): 215.4800
Schätzer für die Standardabweichung (σ): 32.8093

Hypothesentests

[Bearbeiten]

Beispiel:

import numpy as np
import scipy.stats as stats

x_quer = 12.075      # Stichproben-Mittelwert
var    = 0.069       # Stichproben-Varianz
n      = 90          # Stichprobengröße
my_0   = 12.0        # Nullhypothese
alpha  = 0.05        # Signifikanzniveau

z_stat = (x_quer - my_0) / np.sqrt(var / n)
p_val = 2 * (1 - stats.norm.cdf(np.abs(z_stat)))

print(f"Z-Statistik: {z_stat:.4f}")

if p_val < alpha:
    print(f"p-Wert: {p_val:.6f} < alpha:", alpha)
    print("Die Nullhypothese wird verworfen.")
else:
    print(f"p-Wert: {p_val:.6f} > alpha:", alpha)
    print("Die Nullhypothese wird nicht verworfen.")

Ausgabe:

Z-Statistik: 2.7087
p-Wert: 0.006755 < alpha: 0.05
Die Nullhypothese wird verworfen.

Statistische Qualitätskontrolle

[Bearbeiten]

Beispiel (Mittelwertkarte):

import numpy as np
import matplotlib.pyplot as plt

# Gegeben
sollwert = 50.0
varianz = 4.0
stichproben_umfang = 1
daten = [49.5, 50.2, 53.0, 48.1, 52.6, 53.4, 49.8]

# Berechnung
standardabweichung = np.sqrt(varianz)
streuung = standardabweichung / np.sqrt(stichproben_umfang)

cl = sollwert
ucl = cl + 3 * streuung
lcl = cl - 3 * streuung

# Darstellung
plt.plot(daten, marker='o', linestyle='-', color='b', label='Messdaten')
plt.axhline(cl, color='green', linestyle='-', label=f'CL: {cl}')
plt.axhline(ucl, color='red', linestyle='--', label=f'UCL: {ucl:.2f}')
plt.axhline(lcl, color='red', linestyle='--', label=f'LCL: {lcl:.2f}')

plt.title('Mittelwertkarte')
plt.xlabel('Stichprobe')
plt.ylabel('Wert')
plt.legend(loc='lower left')
plt.grid(True)
plt.show()

Ausgabe:

Siehe auch  Shewhart-Regelkarte und  Qualitätsregelkarte.

  • UCL ... Upper Control Limit, Obere Eingriffsgrenze
  • LCL ... Lower Control Limit, Untere Eingriffsgrenze
  • CL ... Center Line, Mittellinie

Ein- und Ausgabe

[Bearbeiten]

print

[Bearbeiten]

Die Anweisung print haben wir schon oft verwendet. Hier soll anhand von Beispielen kurz beschrieben werden, was der Befehl print leisten kann.

print("Hallo", "Welt", 1, sep="-")
print("Hallo", end=" ")
print("Welt")

Ausgabe:

Hallo-Welt-1
Hallo Welt

input

[Bearbeiten]
a = int(input("Zahl 1: "))
b = int(input("Zahl 2: "))

print("a + b = ", a+b)

Ausgabe (nach Eingabe der beiden Ganzzahlen):

Zahl 1: 4
Zahl 2: 5
a + b =  9

Aus Dateien lesen

[Bearbeiten]

Es seinen die datei.txt

Hallo Welt.
Wie geht es dir?
...

und test1.py

dat = open("datei.txt", mode = "r")
print(dat.read())
dat.close()

Ausgabe

Hallo Welt.
Wie geht es dir?
...

Mit dem open()-Befehl wird die Datei datei.txt im Lesemodus geöffnet (r ... read). Mit dem read()-Befehl wird die Datei eingelesen und mittels print ausgegeben.

In Dateien schreiben

[Bearbeiten]
dat = open("datei.txt", mode = "a", encoding = "utf-8")
dat.write("Hänge Zeile an\n")
dat.close()

Die Datei datei.txt sieht nach Abarbeitung des obigen Skripts nun so aus

Hallo Welt.
Wie geht es dir?
...
Hänge Zeile an

Es wird die Datei im Schreibmodus geöffnet (a ... append (anhängend), w ... write (überschreibend)). write() fügt hier also eine Zeile Text am Dateiende ein. close() schließt die Datei wieder.

Das close() kann man sich mit der with-Anweisung auch sparen.

with open("datei.txt", mode="a", encoding="utf-8") as dat:
    dat.write("Hänge Zeile an\n")

Benutzeroberflächen erstellen

[Bearbeiten]

tkinter

[Bearbeiten]
Wikipedia hat einen Artikel zum Thema:


Python bietet standardmäßig das Modul tkinter zur Programmierung von Benutzeroberflächen. Es müssen also bei der Verwendung von tkinter keine externen Module installiert werden. Hier wird eine (sehr) kurze Einführung in das Erstellen von grafischen Oberflächen mittels tkinter gegeben.

import tkinter as tk

win = tk.Tk()
win.title("Hallo Welt!")
win.minsize(300, 50)
but = tk.Button(win, text = "Push the button")
but.pack()
win.mainloop()

Ausgabe:

Ein etwas komplizierteres Beispiel sei nachfolgend gezeigt. Es sollen zwei Strings miteinander verknüpft und ausgegeben werden.

import tkinter as tk

win = tk.Tk()
win.title("Hallo Welt!")

def on_button_clicked():
    str = ent1.get() + ent2.get()
    lab2["text"] = str
 
ent1 = tk.Entry(win)
ent2 = tk.Entry(win)
lab1 = tk.Label(win, text="verknuepfen mit")
lab2 = tk.Label(win, text="") 
but = tk.Button(win, text = "=", command=on_button_clicked)

ent1.pack(side="left")
lab1.pack(side="left")
ent2.pack(side="left")
but.pack(side="left")
ent2.pack(side="left")
lab2.pack(side="left")

win.mainloop()

Ausgabe (vor der Eingabe der Teilstrings):

Ausgabe (nach der Eingabe der Teilstrings und dem Drücken des =-Buttons):

curses

[Bearbeiten]
Wikipedia hat einen Artikel zum Thema:


Mit dem curses-Modul lassen sich u.a. TUIs (Text User Interfaces) erstellen. Ein sehr einfaches Beispiel zur allgemeinen Funktionsweise wird nachstehend geliefert.

import curses

stdscr = curses.initscr()
curses.start_color()
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
stdscr.clear()

stdscr.addstr("Hallo Welt", curses.color_pair(1))
stdscr.refresh()

stdscr.getch()

curses.endwin()

Als Ausgabe sollte Hallo Welt (rote Schrift auf weißem Hintergrund) auf dem Terminal/der Konsole erscheinen. Getestet wurde dies mit openSUSE Tumbleweed, Python-Version 3.13.12. Das entsprechende Python-curses-Package muss installiert sein.

Allgemeine Informationen zur Terminal-/Konsolengröße und Cursorposition liefert folgendes Programm:

import curses

stdscr = curses.initscr()

stdscr.addstr(3, 5, "LINES: %d" % curses.LINES)
stdscr.addstr(4, 5, "COLS:  %d" % curses.COLS)

(y,x) = stdscr.getyx()
stdscr.addstr(5, 5, "Momentane Cursorposition:  [%d, %d]" % (y, x))

(y,x) = stdscr.getbegyx()
stdscr.addstr(6, 5, "Koordinatenursprung:       [%d, %d]" % (y, x))

(y,x) = stdscr.getmaxyx()
stdscr.addstr(7, 5, "Fenstergröße:              [%d, %d]" % (y, x))

stdscr.addstr(11, 2, "Taste drücken -> Ende")
stdscr.refresh()

stdscr.getch()

curses.endwin()

Es sollte sich in etwa folgende Ausgabe ergeben:

    LINES: 44
    COLS:  110
    Momentane Cursorposition:  [4, 15]
    Koordinatenursprung:       [0, 0]
    Fenstergröße:              [44, 110]


Taste drücken -> Ende

Zur Funktionsweise von curses siehe auch das Wikibook ncurses. Zum Verständnis sind dort allerdings elementare Kenntnisse in der Programmiersprache C erforderlich.

Wikipedia hat einen Artikel zum Thema:


Auch für das Qt-Framework gibt es eine Anbindung an Python. Nachfolgend ein einfaches Beispiel.

import sys
from PySide6.QtWidgets import QApplication, QLabel

app = QApplication(sys.argv)
label = QLabel("Hallo Welt!")
label.show()
sys.exit(app.exec())

Ausgabe:

Wikipedia hat einen Artikel zum Thema:


Eine idente Ausgabe, wie oben für Qt gezeigt, erzeugt z.B. folgendes Gtk-Programm:

import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk

def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    lab = Gtk.Label(label="Hallo Welt!")
    win.set_child(lab)
    win.present()

app = Gtk.Application()
app.connect('activate', on_activate)
app.run(None)

Auch für die Benutzung von Qt und Gtk müssen die jeweiligen Packages installiert sein. Getestet wurden die entsprechenden Python-Programme nur unter openSUSE Tumbleweed. Wie das GTK-Paket unter MS Windows 11 installiert wird, siehe z.B. Setting up GTK for Windows.

Damit sei aber das Thema "Benutzeroberflächen erstellen" hier abgeschlossen, da dies schon ein sehr spezielles Aufgabengebiet ist, das eher Informatiker und nicht so sehr Ingenieure anspricht. Bei Bedarf siehe aber ggf. die entsprechenden Links unten in diesem Tutorial. Dort sind weiterführende Informationen zu finden.

Style Guide, flake8, pylint, Black etc.

[Bearbeiten]

Style Guide

[Bearbeiten]

Wie man schönen und richtigen Python-Code schreibt, erfahren Sie in

Formatter und Linter

[Bearbeiten]

Ein Modul, das prüft, ob die Richtlinien im Style Guide eingehalten wurden, ist flake8:

Code formatieren kann man auch mit Black. Z.B. übersetzt black test1.py die Datei test1.py

import sympy as sp

H = sp.Symbol("H", positive=True)
T = sp.Symbol("T", positive=True)
t = sp.Symbol("t")

f = sp.Piecewise(
    (H, (t > 0) & (t < T / 2)),
    (2 * H / T * (t - T / 2), (t > T / 2) & (t < T))
)

f_series = sp.fourier_series(f, (t, 0, T))
sp.pprint(f_series.truncate(4))

in

import sympy as sp

H = sp.Symbol("H", positive=True)
T = sp.Symbol("T", positive=True)
t = sp.Symbol("t")

f = sp.Piecewise(
    (H, (t > 0) & (t < T / 2)), (2 * H / T * (t - T / 2), (t > T / 2) & (t < T))
)

f_series = sp.fourier_series(f, (t, 0, T))
sp.pprint(f_series.truncate(4))

Die Programmausgabe ist

reformatted test1.py

All done! ✨ 🍰 ✨
1 file reformatted.

Der Unterschied zwischen Black und Flake8:

  • Black ist ein Code-Formatter. Er formatiert Ihren Code um, sodass er im Einklang mit PEP 8 steht.
  • Flake8 ist ein   Code-Linter. Flake8 verändert Ihren Code nicht, sondern durchsucht ihn nach potenziellen Fehlern etc.

Am obigen Beispiel sieht man auch, dass flake8 und Black nicht immer einer Meinung sind. Flake8 (flake8 test1.py) würde standardmäßig den mit Black formatierten Code bemängeln:

test1.py:8:80: E501 line too long (80 > 79 characters)

Diese Diskrepanz kann beseitigt werden. Da 79 Zeichen auf modernen Bildschirmen meist als zu kurz empfunden werden, ist ein Limit von 88 Zeichen (Black-Standard) oder mehr empfehlenswert. Um dies zu implementieren, erstellen Sie in Ihrem Projektverzeichnis eine .flake8-Datei mit dem Inhalt

[flake8]
max-line-length = 88

Und schon ignoriert Flake8 dieses Problem.

Ein anderer Linter ist pylint. Der würde beim Abarbeiten des obigen Beispiels, z.B. mit pylint test1.py noch eine Kleinigkeit bemängeln:

************* Module test1
/home/hr/tmp/test1.py:1:0: C0114: Missing module docstring (missing-module-docstring)

------------------------------------------------------------------
Your code has been rated at 8.57/10 (previous run: 8.57/10, +0.00)

Auch pylint muss vor der ersten Verwendung installiert werden (z.B. mittels pip, virtuelle Umgebung, YaST). Die Dokumentation zu pylint findet sich auf [26].

Aufgabe: Fügen Sie einen "module docstring" in die test1.py-Datei ein und testen Sie erneut mit flake8, Black und pylint. Sehen Sie zum Thema docstrings auch PEP 257 – Docstring Conventions.

Es gibt noch weitere Formatierungswerkzeuge für Python-Code. Z.B. Ruff, ein moderner Code-Formatter und -Linter. Mittels ruff check test1.py würde obiger Code geprüft (Linter). ruff format test1.py formatiert den Code (Formatter).

Type Checker

[Bearbeiten]

"Type Checker" sind z.B.

  • mypy
  • pyright
  • ty

Diese prüfen die Datentypen, z.B. in folgendem Code

def greetings(name: str) -> str:
    return "Hello, %s" % name


print(greetings(42))

Python selbst, flake8, ruff oder black würden diesen Code ohne zu Murren akzeptieren. "Type Checker" würden aber sehr wohl Alarm schlagen, z.B. liefert mypy folgende Ausgabe

test1.py:5: error: Argument 1 to "greetings" has incompatible type "int"; expected "str"  [arg-type]
Found 1 error in 1 file (checked 1 source file)

Sonstige Tools

[Bearbeiten]

Andere Tools für die  statische Codeanalyse, die aber für Ingenieure weniger interessant sein dürften, sind z.B.

  • Radon: Liefert verschiedene  Codemetriken (Komplexität, Wartbarkeitsindex ...)
  • Bandit: Findet Sicherheitslücken

Tools für die  dynamische Codeanalyse, z.B.:

  • DynaPyt (Framework zur dynamischen Programmanalyse)
  • cProfile (Profiler)
  • Memory Profiler (Speicheranalyse)
  • Memray (Speicheranalyse)
  • tracemalloc (Speicheranalyse)

Paket- und Projektmanagement (pip-Ersatz etc.):

  • uv
  • Poetry
  • Conda
  • pipx

Packaging-Tools (Freezer) und  Transpiler :

  • pyinstaller
    • erstellt eigenständige, ausführbare Binärdatei
    • kein Cross-Compiler
    • kein Schutz vor Reverse-Engineering
    • langsam
    • packt alles in eine Datei
    • sehr große Datei
    • Befehl, z.B.: pyinstaller --onefile test1.py
    • GUI: auto-py-to-exe
  • cx_Freeze
  • nuitka
    • Übersetzt Python-Code in C/C++-Code und weiter in eine ausführbare Datei
    • kein Cross-Compiler
    • Schutz vor Reverse-Engineering
    • Befehl, z.B.: nuitka --standalone --onefile test1.py
  • cython

Einige Integrierte Entwicklungsumgebungen (IDEs)

[Bearbeiten]

Werden Programmtexte größer und umfangreicher, so ist das Arbeiten mit der interaktiven Programmierumgebung bzw. das direkte Ausführen von Python-Skripten mühsam. Man wünscht sich z.B. Hilfen zum Debuggen oder die automatische Code-Vervollständigung. Zu diesem Zweck wurden IDEs (Integrated Development Environments) geschaffen. Von diesen seinen nachfolgend auszugsweise einige kurz beschrieben. Testen Sie einfach aus, welche davon für Sie bzw. für Ihr Python-Projekt geeignet sind.

IDLE ist die mit dem Python-Programmpaket mitgelieferte IDE. Der Name leitet sich einerseits ab vom Monty-Python-Mitglied Eric Idle, andererseits steht es als Abkürzung für "Integrated Development and Learning Environment. IDLE ist einfach zu bedienen, bietet aber schon einen beachtlichen Leistungsumfang. Nachfolgend wird ein Screenshot zu IDLE geliefert. Rechts ist das Editor-Fenster zu sehen, links die interaktive Programmierumgebung. Um das Beispiel selbst nachvollziehen zu können, starten Sie IDLE. Das geht ähnlich, wie Sie die interaktive Programmierumgebung von Python starten (nur, dass Sie eben das IDLE-Icon doppelklicken und nicht das Python-Icon. Unter Linux geben Sie einfach in einem Terminal idle3.13 o. Ä. ein). Weiter geht es mit "File - Open - ...". Die auszuführende Datei auswählen (im konkreten Fall ein "Hallo-Welt"-Programm). Es erscheint das rechte Fenster. Dort "Run - Run Module" auswählen. Und schon wird im linken Fenster "Hallo Welt!" ausgegeben.

Siehe auch  IDLE.

PyCharm

[Bearbeiten]

PyCharm ist ein kommerzielles Produkt. Es gab aber auch eine kostenlose Community Edition. Seit 2025 sind beide Varianten vereint. Für die ersten 30 Tage sind die Pro-Funktionen frei verfügbar, danach nur noch die Kernfunktionalitäten (oder man bezieht kostenpflichtig die Pro-Version). Zu beziehen ist PyCharm unter dem Weblink [27]. Nachfolgend ein etwas abgewandeltes "Hallo Welt"-Programm, editiert und ausgeführt mit PyCharm.

Siehe auch  PyCharm.

Auch eric ist Open Source und steht unter der GNU General Public License Version 3 oder später. Zu beziehen ist diese Software unter [28].

Siehe auch  eric (Software).

Unter openSUSE Tumbleweed sollte sich eric auch mit YaST installieren lassen. Bei mir gibt es aber dann beim Ausführen des eric-Programms eine Fehlermeldung (Stand März 2026):

...
ModuleNotFoundError: No module named 'PyQt6.QtPdfWidgets'

Umgehen kann man dieses Problem aber wieder mit dem Erstellen einer virtuellen Umgebung, in etwa so

python3.13 -m venv ~/tmp/venv1
cd ~/tmp/venv1/bin
./python3.13 -m pip install --upgrade --prefer-binary eric-ide
./eric7_ide

PyScripter

[Bearbeiten]

Vom Funktionsumfang vergleichbar mit den vorherigen IDEs ist PyScripter. Auch PyScripter ist Open Source. Die Projekt-Homepage findet sich auf [29]. PyScripter ist nur für MS Windows verfügbar.

Spyder IDE

[Bearbeiten]

Spyder enthält bereits eine stabile Python-Version und etliche Module (z.B. matplotlib, numpy, control). Ansonsten kann dieses Softwarepaket vom Funktionsumfang her mit den anderen genannten IDEs locker mithalten. Spyder wurde unter der MIT-Lizenz veröffentlicht. Diese Software findet sich auf [30].

Siehe auch  Spyder (Software)

Eclipse IDE

[Bearbeiten]

Die  Eclipse-IDE kann für Python aufgerüstet werden. Dazu gibt es das PyDev-Plugin. Installiert wird es über

  • Help > Eclipse Marketplace...
  • Find - PyDev - Install

Danach muss noch der Pfad zum Python-Interpreter festgelegt werden

  • Window > Preferences > PyDev > Interpreters > Python Interpreter > New ...

Das Ergebnis ist ähnlich wie im folgenden Bild, nur dass statt C/C++ Python Verwendung findet.

Sonstige

[Bearbeiten]

Die genannten IDEs sind nicht die Einzigen. Es gibt, um dem Image Pythons als beliebteste Programmiersprache gerecht zu werden, noch einige andere. Sowohl Open Source-Programme als auch kommerzielle Programme sind im Web zu finden, z.B. Thonny oder  Visual Studio Code. Unter Linux kann man auch  KDevelop, ausgestattet mit dem Python3-Plugin, einsetzen. Braucht man den Umfang von ausgewachsenen IDEs nicht, so kann man auch normale Texteditoren verwenden (z.B.  Geany oder  Kate).

Debuggen und Testen

[Bearbeiten]

Das Debuggen und Testen von Programmen sind wichtige Bestandteile der Programmierung. Syntaxfehler lassen sich i.A. leicht beheben. Schwieriger ist das Eingrenzen von logischen Fehlern, die ev. nur in bestimmten Situationen auftreten und keine explizite Fehlermeldung hervorrufen. Das Programm liefert falsche Ergebnisse oder es stürzt aus heiterem Himmel ab. Um das zu verhindern gibt es verschiedene Werkzeuge, die bei der Fehlersuche behilflich sein können. Vorerst siehe aber zwecks Begriffsklärung noch folgende Links:

Das Modul pdb

[Bearbeiten]

Python bringt schon ein Modul zum Debuggen mit. Siehe z.B. pdb — The Python Debugger. Komfortabler lässt sich das aber mittels Integrierter Entwicklungsumgebungen (IDEs) angehen.

Debuggen mit IDEs

[Bearbeiten]

Für die IDEs IDLE und Spyder sei kurz auf die entsprechenden Webseiten verwiesen:

Dort wird die Vorgehensweise auch mittels Screenshots erläutert.

assert

[Bearbeiten]

assert ... behaupten, zusichern ( Assertion (Informatik))

Python-Code:

def print1(x, y):
    assert type(x) == float
    assert type(y) == float
    assert y != 0.0
    print(x/y)

print1(10., 5.)
print1(10., 0.)

Ausgabe:

2.0
Traceback (most recent call last):
  File "/home/hr/Develop/test1.py", line 8, in <module>
    print1(10., 0.)
  File "/home/hr/Develop/test1.py", line 4, in print1
    assert y != 0.0
           ^^^^^^^^
AssertionError

Python-Code:

def print1(x, y):
    assert type(x) == float
    assert type(y) == float
    assert y != 0.0
    print(x/y)

print1(10., 5.)
print1("10.", "5.")

Ausgabe:

2.0
Traceback (most recent call last):
  File "/home/hr/Develop/test1.py", line 8, in <module>
    print1("10.", "5.")
  File "/home/hr/Develop/test1.py", line 2, in print1
    assert type(x) == float
           ^^^^^^^^^^^^^^^^
AssertionError

Aber auch bei nachfolgendem Code gibt es eine Fehlermeldung:

def print1(x, y):
    assert type(x) == float
    assert type(y) == float
    assert y != 0.0
    print(x/y)

print1(10., 5.)
print1(10, 5)

Ausgabe:

2.0
Traceback (most recent call last):
  File "/home/hr/Develop/test1.py", line 8, in <module>
    print1(10, 5)
  File "/home/hr/Develop/test1.py", line 2, in print1
    assert type(x) == float
           ^^^^^^^^^^^^^^^^
AssertionError

Damit letzteres funktioniert, kann man den Programmcode so umschreiben:

def print1(x, y):
    assert type(x) == float or type(x) == int
    assert type(y) == float or type(y) == int
    assert y != 0.0
    print(x/y)

print1(10., 5.)
print1(10, 5)

Ausgabe:

2.0
2.0

Und jetzt fangen wir den AssertionError auf:

def print1(x, y):
    try:
        assert type(x) == float or type(x) == int
        assert type(y) == float or type(y) == int
        assert y != 0.0
        print(x/y)
    except(AssertionError):
        print("Hallo")

print1(10., 5.)
print1("10.", "5.")

Ausgabe:

2.0
Hallo

Ich hoffe, es ist wenigstens im Ansatz klar geworden, wofür assert gut sein kann. Ausschalten kann man die assert-Überprüfung übrigens mit dem Python-Schalter -O.

Doctests

[Bearbeiten]

Innerhalb eines Docstrings kann die Arbeit im interaktiven Modus simuliert werden. Nach den Promptzeichen (>>>) erfolgen dann bei unserem Beispiel innerhalb des Docstrings simulierte Aufrufe der Funktion print1(). Danach folgen jeweils die Sollresultate. Wird das Modul oder die Datei als Hauptprogramm aufgerufen, so wird die Funktion doctest.testmode() aufgerufen und ein Bericht auf der Konsole ausgegeben. Wird das Modul nicht als Hauptprogramm aufgerufen, sondern importiert, dann wird diese testmod-Funktion nicht aufgerufen. D.h. dieser Code kann sowohl für Testzwecke als auch für den produktiven Einsatz verwendet werden. Das ist auch sinnvoll, weil wenn man Teile der Datei immer löschen bzw. einfügen müsste, so würden sich Fehlerquellen auftun. Das würde den Sinn und Zweck von Doctests konterkarieren.

def print1(x=0., y=1.):
    """ Dividiere zwei Zahlen
    Autor: Intruder
    Datum: 12.08.2025

    >>> print1(2., 1.)
    2.0
    >>> print1(5., 2.)
    2.5
    >>> print1(5.)
    5.0
    """
    print(x/y)

if __name__ == "__main__":
    import doctest
    doctest.testmod(verbose=True)

Ausgabe:

Trying:
    print1(2., 1.)
Expecting:
    2.0
ok
Trying:
    print1(5., 2)
Expecting:
    2.5
ok
Trying:
    print1(5.)
Expecting:
    5.0
ok
1 items had no tests:
    __main__
1 items passed all tests:
   3 tests in __main__.print1
3 tests in 2 items.
3 passed and 0 failed.
Test passed.

Das gezeigte Beispiel ist so ziemlich das einfachste, das es gibt. Für weiterführende Details siehe z.B.:

pytest

[Bearbeiten]

Siehe zu diesem Thema auch  Modultest.

pytest ist ein externes Modul und muss vorab installiert werden, z.B. mittels

pip install -U pytest
pip install -U pytest-html 

Python-Code, Datei test1.py:

def add(x, y):
    return x + y

def test_answer():
    assert add(1, 1) == 3

Starten von pytest in der Konsole:

pytest test1.py

Ausgabe:

==================================================== test session starts ====================================================
platform linux -- Python 3.12.11, pytest-8.4.1, pluggy-1.6.0
rootdir: /home/hr/Develop
plugins: anyio-4.10.0, metadata-3.1.1, html-4.1.1
collected 1 item                                                                                                            

test1.py F                                                                                                            [100%]

========================================================= FAILURES ==========================================================
________________________________________________________ test_answer ________________________________________________________

    def test_answer():
>       assert add(1, 1) == 3
E       assert 2 == 3
E        +  where 2 = add(1, 1)

test1.py:6: AssertionError
================================================== short test summary info ==================================================
FAILED test1.py::test_answer - assert 2 == 3
===================================================== 1 failed in 0.09s =====================================================

Hier erhalten wir einen Fehler, da 1+1 eindeutig ungleich 3 ist. Aber aus irgendeinem Grund wollte der Programmierer oder Tester in diesem Fall, dass dies so ist. Testfälle werden übrigens mit dem Präfix test_ eingeleitet.

Python-Code:

def add(x, y):
    return x + y + 1

def test_answer():
    assert add(1, 1) == 3 

Ausgabe:

==================================================== test session starts ====================================================
platform linux -- Python 3.12.11, pytest-8.4.1, pluggy-1.6.0
rootdir: /home/hr/Develop
plugins: anyio-4.10.0, metadata-3.1.1, html-4.1.1
collected 1 item                                                                                                            

test1.py .                                                                                                            [100%]

===================================================== 1 passed in 0.01s =====================================================

Jetzt ist alles in Ordnung. Weiterführendes siehe z.B.

unittest

[Bearbeiten]

Auch unittest dient zur Durchführung von Testreihen, ist aber Bestandteil von Python. Hier wird vorerst nicht näher darauf eingegangen. Siehe z.B.

Lt. Inden: Python Challenge; dpunkt, 2021, Seite 481 soll unittest weniger komfortabel als pytest sein.

Einen Vergleich von unittest mit pytest findet man in

Python und Anwendungsprogramme

[Bearbeiten]

Bisher stand immer alleine die Programmiersprache Python (ev. unter Einbeziehung von Modulen) im Mittelpunkt der Betrachtungen. Aber Python kann auch als Makrosprache für Anwendungsprogramme auftreten. Als Beispiele seien  FreeCAD und  LibreOffice genannt.

FreeCAD

[Bearbeiten]

FreeCAD ist ein freies 3D-CAD-Programm. Hier soll nicht auf die Bedienung dieses CAD-Pakets eingegangen werden, sondern nur auf die Möglichkeit, mittels Python Makros zu schreiben. Als einfacher Einstieg soll ein Makro erstellt werden, welches eine Kugel (rot) und einen Quader (blau) zeichnet. Folgende Vorbereitungsschritte sind erforderlich (es sei vorausgesetzt, dass FreeCAD schon am Rechner installiert ist. Downloaden können Sie das Programm von der Website [31]):

  • FreeCAD starten
  • Leere Datei erstellen
  • Makro > Makros > Erstellen ...

Es öffnet sich ein leeres Editorfenster, in das Sie folgenden Code eingeben können:

import FreeCAD
import Part

doc = FreeCAD.newDocument()

# Kugel
kugel = Part.makeSphere(10)
form_element = doc.addObject("Part::Feature", "Kugel")
form_element.Shape = kugel
kug = FreeCAD.ActiveDocument.getObject("Kugel")
kug.ViewObject.ShapeColor = (1.0, 0.0, 0.0)
neuePosition = App.Vector(5, 2.5, 2.5)
kug.Placement = App.Placement(neuePosition, kug.Placement.Rotation)

# Quader
quader = Part.makeBox(5, 5, 50)
form_element = doc.addObject("Part::Feature", "Quader")
form_element.Shape = quader
quad = FreeCAD.ActiveDocument.getObject("Quader")
quad.ViewObject.ShapeColor = (0.0, 0.0, 1.0)

doc.recompute()

Diesen Code können Sie nun ausführen:

  • Makro > Makro ausführen

Es ergibt sich folgende Ausgabe (gedreht und gezoomt):

Siehe auch Anleitung Skripterstellung mit Python. Getestet wurde obiges Beispiel mit FreeCAD 1.1.0 unter Linux und 1.1.1 unter MS Windows.

LibreOffice

[Bearbeiten]

LibreOffice ist ein freies Officepaket ([32]). Hier soll nur das Tabellenkalkulationsprogramm Calc kurz betrachtet werden. Es seinen in den ersten 3 Zellen (A1 bis A3) Zahlen gegeben. Diese sollen mit einem Python-Makro addiert und das Resultat in der Zelle A5 ausgegeben werden. Auch hier sind Vorbereitungsarbeiten nötig:

  • zuerst muss unter Linux das Verzeichnis ~/.config/libreoffice/4/user/Scripts/python erstellt werden
  • für MS Windows ist es das Verzeichnis %APPDATA%\LibreOffice\4\user\Scripts\python
    • drücken Sie zuerst Win + R (es öffnet sich das Ausführen-Fenster)
    • geben Sie %appdata% ein, danach drücken Sie Enter (es öffnet sich der Explorer)
    • navigieren Sie zu dem genannten Verzeichnis bzw. erstellen Sie das Verzeichnis
  • in diesem Verzeichnis wird dann mit einem beliebigen Texteditor das Python-Makro erstellt, in unserem Fall die Datei summiere_zellen.py:
import uno

def summiere_zellen(*args):
    # Zugriff auf das aktuelle Dokument und das aktive Tabellenblatt
    ctx = uno.getComponentContext()
    smgr = ctx.getServiceManager()
    desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx)
    doc = desktop.getCurrentComponent()
    sheet = doc.getCurrentController().getActiveSheet()

    # Werte aus den Zellen A1 bis A3 auslesen
    w1 = sheet.getCellRangeByName("A1").Value
    w2 = sheet.getCellRangeByName("A2").Value
    w3 = sheet.getCellRangeByName("A3").Value

    # Addition der drei Werte
    summe = w1 + w2 + w3

    # Ergebnis in die Zelle A5 schreiben
    sheet.getCellRangeByName("A5").Value = summe
  • siehe dazu ggf. auch [33].

Weiter geht es in LibreOffice Calc mit dem Menü Extras > Makros > Makros verwalten > Python. Dort wird das Makro summiere_zellen ausgeführt. Es ergibt sich z.B. folgendes Resultat

Das Kürzel uno steht für Universal Network Objects. Etwas einfacher geht's auch so:

def summiere_zellen():
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    sheets = model.getSheets()
    sheet = sheets.getByIndex(0)
    
    w1 = sheet.getCellRangeByName("A1").Value
    w2 = sheet.getCellRangeByName("A2").Value
    w3 = sheet.getCellRangeByName("A3").Value
    
    cell = sheet.getCellRangeByName("A5")    
    cell.setValue(w1 + w2 + w3) 

Empfohlen wird auch, das Erweiterungspaket APSO (Alternative Python Script Organizer, apso.oxt) zu installieren. Die Vorgehensweise wird hier nicht gezeigt, sondern nur darauf hingewiesen, dass man das einfach "googeln" kann. Siehe zur Python-Programmierung für LibreOffice auch Makros/Python-Handbuch. Getestet wurden obige Beispiele mit LibreOffice 26.2.3.2 unter Linux und 26.2.1.2 unter MS Windows.

Ausblick

[Bearbeiten]

Dies war eine kurze Einführung in die Berechnungs- und Darstellungsmöglichkeiten mit Python. Es sollten etliche relevante Themen behandelt, oder zumindest kurz angesprochen worden sein. Wem dieser Text nicht ausreichend ist, der sei auf die entsprechenden weiterführenden Weblinks, Bücher und die Python-Hilfefunktion verwiesen. Python kennt noch viel mehr Befehle, als hier dargestellt wurden. Das Themenspektrum ist auch durch die Einbindung externer Module fast beliebig erweiterbar.

Weblinks

[Bearbeiten]

Python allgemein

[Bearbeiten]

Externe mathematische Module

[Bearbeiten]

Externe Module für Grafiken

[Bearbeiten]

Erstellung von User Interfaces

[Bearbeiten]

Erstellen virtueller Umgebungen

[Bearbeiten]

Sonstige

[Bearbeiten]

Bücher

[Bearbeiten]

Gedruckte Bücher, OpenBooks, Magazine

[Bearbeiten]

Andere Wikibooks

[Bearbeiten]