Ing Mathematik: Python
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 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 Leap z.B. auch „python3“ oder „python3.11“) in einem Linux-Terminal ein, schließen den Befehl mit der RETURN-Taste ab, und schon startet Python im interaktiven Modus.
Es gibt auch noch andere Möglichkeiten Python zwecks Programmausführung zu starten, z. B. den Shebang (#!/usr/bin/python) am Beginn eines Python-Scripts. Dann kann das Script mit ./Script.py ausgeführt werden. 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 (die Berechtigungen zum Ausführen der Datei müssen natürlich noch richtig gesetzt werden).
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 mit 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 mit der Python-Version 3.13.9 (nur vereinzelt, ab November 2025)
An Beliebtheit rangiert Python mit Stand Juni 2025 mit einem Rating von 25,87% an 1. Stelle (lt. TPCI - TIOBE Programming Community Index). Lt. GitHub Top 50 Programming Languages Globally lag Python im Q1/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.
-
Python-Logo
-
Guido van Rossum (geb. 1956), der Erfinder von Python
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.vortan) - Berechnen Sie mit Python den Ausdruck . Siehe für die Exponentialfunktion im Python-Hilfesystem auch den Befehl
math.exp. Alternativ kann auch die Konstantemath.eeingesetzt werden. Potenzieren kann man bei Python mit dem **-Operator (z.B. 2**3 = 8). Für gibt esmath.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 cmdein 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!
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" print(str1) print(str2) print(str3)
Ausgabe:
ABC Hallo Welt, Grüetzi Schwyzer, Servus an alle UVWXYZ
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:
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
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]if
[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
[Bearbeiten]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.
pass
[Bearbeiten]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, a*b
r1 = calcFunc(8, 9)
r2 = calcFunc(8.0, 9.0)
print(r1)
print(r2)
Ausgabe:
(17, 72) (17.0, 72.0)
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 in Endeffekt eingibt. Im obigen Beispiel können statt Integer-Typen auch Float-Typen eingegeben werden.
Tupel, Listen und andere
[Bearbeiten]
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,)
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:
- Starten Sie ein Terminal (bei Windows die Eingabeaufforderung).
- 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.
2D
[Bearbeiten]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()
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.
3D
[Bearbeiten]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 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() ax.contourf(x, y, z) 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 (die prinzipielle Vorgehensweise wurde oben bereits gezeigt und sei hier nicht wiederholt). Ein Beispiel zu solch 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
Vektoren und Matrizen
[Bearbeiten]Zahlenfolgen
[Bearbeiten]from numpy import *
start = 0
stop = 10
step = 2
num = 10
r = arange(start, stop, step)
l = linspace(start, stop, num)
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. ]
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:
import numpy as np z = np.zeros((3, 2)) print(z)
Ausgabe:
[[0. 0.] [0. 0.] [0. 0.]]
Einheitsmatrix:
import numpy as np z = np.eye(3) print(z)
Ausgabe:
[[1. 0. 0.] [0. 1. 0.] [0. 0. 1.]]
Matrix mit lauter Einsen:
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 [18].
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)]
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.
import findiff 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 = findiff.FinDiff(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). Das im Buch "Steinkamp: Der Python-Kurs für Ingenieure und Naturwissenschaftler, Rheinwerk" verwendete Modul "scipy.misc" ist veraltet (deprecated ... missbilligt) und wird in einer kommenden SciPy-Version entfernt werden.
Symbolisches Differenzieren
[Bearbeiten]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]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)
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).
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 .
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.).
Stochastik
[Bearbeiten]Die Stochastik ist ein sehr weites Feld. Hier werden nur einige wenige sehr einfache, aber wichtige Themen 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 und pandas kann man Stochastik in Python betreiben. Dies wird hier aber nicht gemacht.
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]import statistics
werte = [1, 3, 4, 4, 1, 7, 9, 1, 2, 3]
s = statistics.stdev(werte)
print("Standardabweichung = ", s)
Ausgabe:
Standardabweichung = 2.6770630673681683
Kombinatorik
[Bearbeiten]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
Ein- und Ausgabe
[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]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):
Style Guide und flake8
[Bearbeiten]Wie man schönen und richtigen Python-Code schreibt, erfahren Sie in
Ein Modul, das prüft, ob die Richtlinien im Style Guide eingehalten wurden, ist flake8:
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
[Bearbeiten]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). 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 [19]. Nachfolgend ein etwas abgewandeltes "Hallo Welt"-Programm, editiert und ausgeführt mit PyCharm.
Siehe auch PyCharm.
Eric
[Bearbeiten]Auch eric ist Open Source und steht unter der GNU General Public License Version 3 oder später. Zu beziehen ist diese Software unter [20].
Siehe auch eric (Software).
PyScripter
[Bearbeiten]Vom Funktionsumfang vergleichbar mit den vorherigen IDEs ist PyScripter. Auch PyScripter ist Open Source. Die Projekt-Homepage findet sich auf [21]. 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 [22].
Siehe auch Spyder (Software)
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. Braucht man den Umfang von ausgewachsenen IDEs nicht, so kann man auch normale Texteditoren verwenden (z.B. Geany).
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
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 Homepage
- NumPy
- NumPy for MATLAB users
- SciPy
- SymPy
- Matplotlib
- tkinter - Python interface to Tcl/Tk
- findiff
- pandas
- VPython
- Python Control Systems Library
- regex - Regular Expressions
Bücher
[Bearbeiten]- Diverse: c't Python Lernen, Verstehen, Anwenden; Heise, 2022
- Ernesti, Kaiser: Python3 - das umfassende Handbuch; 5. Aufl., Rheinwerk, OpenBook
- Inden: Python Challenge; dpunkt, 2021, ISBN 978-3-86490-809-5
- Klein: Numerisches Python; 2. Aufl., Hanser, 2023, ISBN 978-3-446-47170-2
- Steinkamp: Der Python-Kurs für Ingenieure und Naturwissenschaftler; Rheinwerk, 2021, ISBN 978-3-8362-7316-9
- Weigend: Python 3 - Das umfassende Praxisbuch; 9. Aufl., mitp, 2022, ISBN 978-3-7475-0544-1
- Woyand: Python für Ingenieure und Naturwissenschaftler; 4. Aufl., Hanser, 2021, ISBN 978-3-446-46483-4



































