Software Engineering II - Kapitel 2 (Python Einführung) - WS 2024/25

Summary

This chapter introduces Python programming in the Software Engineering II course for the winter semester 2024/25. It covers key topics such as variables, datatypes, operators, control structures, along with modules, classes, and the Python standard library. The document also discusses installation, interpreters, and different development environments for Python.

Full Transcript

Software Engineering II Vorlesung | Kapitel 2 Wintersemester 2024/25 Prof. Dr. Norman Lahme-Hütig Informatik/Wirtschaftsinformatik, Schwerpunkt Web Engineering Corrensstraße 25 fon +49 (0)251.83 65-190 [email protected] D-48149 Münster fax +49 (0)251.83 65-525 www.fh-muens...

Software Engineering II Vorlesung | Kapitel 2 Wintersemester 2024/25 Prof. Dr. Norman Lahme-Hütig Informatik/Wirtschaftsinformatik, Schwerpunkt Web Engineering Corrensstraße 25 fon +49 (0)251.83 65-190 [email protected] D-48149 Münster fax +49 (0)251.83 65-525 www.fh-muenster.de Kapitel 2 Einführung in Python Œ Einleitung  Variablen, Datentypen und Operatoren Ž Kontrollstrukturen, Funktionen und Fehlerbehandlung  Module, Klassen und Typannotationen  Comprehensions, Iteratoren und Generatoren ‘ Standard-Bibliothek ’ Nebenläufige Programmierung Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) 2 Python Python ist eine dynamisch typisierte, multiparadigmatische Programmiersprache § Entwickelt von Guido van Rossum (gestartet im Dezember 1989, Open Source) § Schwerpunkt: Objektorientierung § Sehr beliebt für Data Science und Künstliche Intelligenz Webseiten § Hauptseite: https://www.python.org § Dokumentation: https://docs.python.org/3/ In der Veranstaltung wird Python 3.12.x betrachtet. Bildquelle: https://www.python.org/community/logos/ Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 3 Python Wesentliche Eigenschaften § Python-Code wird interpretiert § Python ist vorwiegend objektorientiert Alle Werte und Funktionen sind Objekte § Ermöglicht das Überladen von Operatoren Durch Definition von Methoden mit speziellen Namen können Standardoperatoren für eigene Klassen definiert werden § Bietet automatisches Speichermanagement (Garbage Collection) § Umfangreiche Standard-Bibliothek § Mehr als 480.000 3rd-Party-Pakete im Python Package Index (PyPI)1 u. a. NumPy, pandas, SciPy, Matplotlib, NLTK, scikit-learn, simpleai 1 https://pypi.org Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 4 Python Implementierungen CPython § Referenzimplementierung (geschrieben in C) § Kompiliert Python-Code in einen Bytecode, bevor dieser interpretiert wird § Interpreter ist erweiterbar (durch C/C++-Module) § Verwendet einen Global Interpreter Lock (GIL)1 Weitere Implementierung (Auswahl) § PyPy: JIT-Compiler zur Performancesteigerung (https://www.pypy.org) § Jython: JVM-basiert (https://www.jython.org) § IronPython:.NET-Framework-Integration (https://ironpython.net) § MicroPython: Optimiert für Mikrocontroller (https://micropython.org) 1 Innerhalb eines Prozesses kann nur ein Thread Python-Bytecode ausführen (→ kein Problem mit Thread Safety). Zahlreiche langlaufende Operationen sind jedoch nicht in Python implementiert und laufen außerhalb des GILs (z. B. I/O, Bildverarbeitung etc.). Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 5 Installation Linux (Debian/Ubuntu)1 Achtung Nicht die aktuelle Version $ sudo apt-get update 3.13.x installieren!3 $ sudo DEBIAN_FRONTEND=noninteractive apt-get -y install python3 python3-venv macOS Installationsprogramm für Version 3.12.x herunterladen und ausführen: https://www.python.org/downloads2 Windows Installationsprogramm für Version 3.12.x herunterladen und als Administrator ausführen: https://www.python.org/downloads Dabei "Add Python 3.12 to PATH" und "Install Now" wählen 1 Zur Installation für andere Linux-Distributionen vgl. https://docs.python.org/3/using/unix.html#on-linux 2 Installation der Default SSL Root-Zertifikate (für HTTPS-Anfragen): /Applications/Python 3.12/Install Certificates.command 3 Bestimmte Pakete für Python 3.13.x existieren ggf. noch nicht im Wheel-Format und müssten daher lokal gebaut werden Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 6 Python Interpreter Aufruf des Interpreters im interaktiven Modus (REPL) Linux/macOS Windows $ python3 $ python Mit help() bzw. help(obj) wird eine interaktive Hilfe bzw. Hilfe zu einem Objekt angezeigt Ausführen eines Skripts Linux/macOS Windows $ python3 myscript.py $ python myscript.py Python 3 nimmt per Default an, dass Quellcode-Dateien UTF-8 kodiert sind Anmerkung Bei Verwendung einer virtuellen Umgebung kann der Interpreter auch unter Linux/macOS mit python aufgerufen werden Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 7 Virtuelle Umgebung Da verschiedene Projekte i. d. R. unterschiedliche Versionen von Paketen benötigen, wird die Einrichtung einer virtuellen Umgebung empfohlen Projekt mit virtueller Umgebung (venv) aufsetzen Linux/macOS Windows $ mkdir my-project; cd my-project $ mkdir my-project; cd my-project $ python3 -m venv.venv $ python -m venv.venv Virtuelle Umgebung aktivieren Linux/macOS Windows $ cd my-project $ cd my-project $ source.venv/bin/activate $.\.venv\Scripts\activate Nach dem Aktivieren der virtuellen Umgebung kann pip aktualisiert werden durch: pip install - -upgrade pip Vgl. https://docs.python.org/3/tutorial/venv.html Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 8 Package Installer: pip pip ist ein Tool zur Installation von Python-Paketen aus dem Python Package Index (PyPI) und anderen Repositories3 Installation eines Pakets Deinstallation eines Pakets $ pip install $ pip uninstall Abhängigkeiten werden mitinstalliert2 Aufzeigen veralteter Pakete Aktualisieren eines Pakets $ pip list --outdated $ pip install --upgrade Auflisten installierter Pakete Auflisten der Paket-Dateien $ pip list $ pip show --files 1 Im Sinne von Python-Software-Distributionen; nicht zu verwechseln mit den Paketen, die im Python Quellcode per import eingebunden werden 2 Die Abhängigkeiten des Pakets sind in dessen Datei setup.py definiert 3 Dokumentation zu pip: https://pip.pypa.io/en/stable/ Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 9 Package Installer: pip Quellcode-Distributionen vs. Wheels pip kann Pakete sowohl anhand ihres Quellcodes als auch im Wheel-Format installieren Wheel Wheel ist ein Built-Distributionsformat, das insbesondere bei Paketen mit C/C++- Erweiterungen zu einer deutlich schnelleren Installation führt, da diese nicht lokal gebaut werden müssen Ein Paket in diesem Format wird ebenfalls als Wheel bezeichnet Anmerkung Wenn für ein Paket mit C/C++-Erweiterungen kein zum Betriebssystem und der Python-Version passendes Wheel existiert, dann wird ein C/C++-Compiler benötigt, um das Paket anhand des Quellcodes zu bauen1 1 Die Verwendung der Quellcode-Distribution kann über pip install --no-binary :all: erzwungen werden Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 10 Package Installer: pip Datei requirements.txt In einem Python-Projekt können die benötigten Pakete in der Datei Für distribuierbare requirements.txt1 festgehalten werden Anwendungen wird stattdessen die Datei setup.py verwendet foo bar == 1.2.3 baz >= 1.2.3, < 2.0 Die Datei kann automatisch erstellt werden, wobei die aktuell installierten Pakete festgehalten werden $ pip freeze > requirements.txt Installation aller Pakete gemäß requirements.txt $ pip install -r requirements.txt 1 Zum Format für die Angabe der Version vgl. https://www.python.org/dev/peps/pep-0440/#version-specifiers. Per Konvention wird die Datei requirements.txt genannt. Oftmals werden Varianten verwendet, z. B. dev-requirements.txt zur Beschreibung der für die Entwicklung benötigten Pakete. Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 11 Entwicklungsumgebungen PyCharm § Entwickelt von JetBrains § Professional und Community Edition § https://www.jetbrains.com/pycharm/ Spyder § Scientific Python Development Environment PyCharm1 § https://www.spyder-ide.org Eclipse + PyDev § PyDev ist ein Eclipse-Plugin § http://www.pydev.org Spyder2 1 Bildquelle: https://www.jetbrains.com/pycharm/ 2 Bildquelle: https://www.spyder-ide.org Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 12 Entwicklungsumgebungen Visual Studio Code Visual Studio Code ist ein sehr populärer, leichtgewichtiger Quellcode-Editor1 Wesentliche Merkmale § Verfügbar für Windows, macOS und Linux § Erweiterbar durch sog. Extensions § Unterstützt u. a. C++, Go, Java, JavaScript, Python, TypeScript Starten aus der Kommandozeile2 $ cd my-project $ code. Visual Studio Code erkennt eine ggf. vorhandene virtuelle Umgebung und aktiviert diese automatisch, sobald eine Python-Datei ausgewählt wird Es muss explizit ein weiteres Terminal geöffnet werden, damit in diesem die virtuelle Umgebung aktiviert wird 1 Hauptseite: https://code.visualstudio.com 2 Hierzu muss einmalig im Menü View > Command Palette… das Kommando Shell Command: Install 'code' command in PATH ausgeführt werden Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 13 Entwicklungsumgebungen Visual Studio Code: Python-Erweiterung Wesentliche Features § Syntax Highlighting § Automatisches Einrücken § Autocompletion § Refactoring § Linting § Direktes Ausführen von selektiertem Python-Code (Shift + Enter) Installation Beliebige Datei mit Erweiterung.py anlegen und den Hinweisen folgen Zur Python-Erweiterung vgl. https://marketplace.visualstudio.com/items?itemName=ms-python.python Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 14 Entwicklungsumgebungen JupyterLab JupyterLab ist eine webbasierte Entwicklungsumgebung für Jupyter Notebooks, Quellcode und Daten Wesentliche Merkmale § Ermöglicht die Erstellung/Arbeit mit Jupyter Notebooks, Markdown-Dateien, Text- Dateien, Konsolen etc. Jupyter Notebooks erlauben die integrierte und interaktive Eingabe und Ausführung von Quellcode verschiedener (Programmier-)sprachen § Verfügbar für alle Platformen, auf denen Python läuft § Erweiterbar durch sog. Extensions Dokumentation: https://jupyterlab.readthedocs.io/en/latest/index.html Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 15 Entwicklungsumgebungen JupyterLab Installation $ pip install jupyterlab Server starten (lokal) $ jupyter lab Der Server kann dann nur über localhost erreicht werden Server starten (öffentlich) $ jupyter lab --ip='*' --NotebookApp.token='' Der Server kann von jedem Rechner aus erreicht werden Ohne die Option --NotebookApp.token='' ist eine Anmeldung über ein Token erforderlich Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 16 Grundlegendes zur Syntax Anweisungen Kein expliziter Abschluss Anweisungen werden nicht durch ein Semikolon o. Ä. abgeschlossen msg = 'Hello World' Mehrzeilige Anweisungen Anweisungen können sich über mehrere Zeilen erstrecken ggf. ist ein explizites Trennzeichen (\) erforderlich print('Hello', msg = 'Hello ' + \ 'World') 'World' In beiden Fällen ist die Einrückung nicht erforderlich Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 17 Grundlegendes zur Syntax Einrückungen Codeeinrückung ist Teil der Syntax Codeeinrückung definiert, welche Anweisungen zusammengehören for word in ['foo', 'bar', 'baz']: if word.startswith('b'): print(word) print('done') Empfehlung Zur Einrückung sollten Leerzeichen statt Tabulatoren verwendet werden (hier: 2 Leerzeichen) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 18 Grundlegendes zur Syntax Kommentare Ein Kommentar wird durch ein #-Zeichen eingeleitet # Dies ist ein Kommentar foo = 42 # noch ein Kommentar Anmerkung Es gibt keine spezielle Syntax für mehrzeilige Kommentare Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 19 Grundlegendes zur Syntax Docstrings Ein Docstring ist ein String-Literal, das als erste Anweisung in einem Modul, einer Klasse, einer Funktion oder einer Methode steht und der Dokumentation dient Begrenzer sind drei Anführungszeichen def foo(): def bar(): """Ein einzeiliger Docstring.""" """ return 'foo' Ein mehrzeiliger Docstring. """ return 'bar' Ermittlung zur Laufzeit print(foo.__doc__) # Ausgabe: Ein einzeiliger Docstring. Zu weiteren Details vgl. https://www.python.org/dev/peps/pep-0257 Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 20 Konsolenein- und -ausgabe Ausgabe Über die Built-in-Funktion print() können beliebig viele Werte ausgegeben werden Sie werden durch jeweils ein Leerzeichen voneinander getrennt foo = 42 bar = 'ist die Antwort' print(foo, bar) # Ausgabe: 42 ist die Antwort Eingabe Die Built-in-Funktion input() ermöglicht die Eingabe einer Zeichenkette name = input('Bitte geben Sie Ihren Namen ein: ') Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 21 Code Linter Pylint Pylint ist der De-Facto-Standard für Linting von Python Code Features § Überprüfung der Einhaltung von Coding Standards1 § Erkennen von Fehlern und Code Smells § Konfigurierbar und erweiterbar über Plugins Installations-Optionen § Als Erweiterung in Visual Studio Code https://marketplace.visualstudio.com/items?itemName=ms-python.pylint § Alternativ als Kommandozeilentool $ pip install pylint Dokumentation: http://pylint.pycqa.org 1 Insbesondere wird die Einhaltung des Python Style Guide überprüft. Vgl. https://www.python.org/dev/peps/pep-0008/. Bildquelle: https://github.com/PyCQA/pylint/blob/master/doc/logo.png Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 22 Code Linter Pylint Konfiguration Das Verhalten von Pylint kann über die Datei pyproject.toml im Wurzelverzeichnis eines Python-Projekts gesteuert werden [tool.pylint.FORMAT] indent-string=' ' [tool.pylint.BASIC] good-names=['i', 'j', 'k', 'ex', 'Run', '_', 'x', 'y', 'z'] bad-names=['foo', 'bar', 'baz'] Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 23 Quellcode-Formatierer autopep8 autopep8 ist ein Quellcode-Formatierer für Python Code Features § Konform zum PEP 8 Style Guide § Konfigurierbar § Einfache Integration in Visual Studio Code Installations-Optionen § Als Erweiterung in Visual Studio Code https://marketplace.visualstudio.com/items?itemName=ms-python.autopep8 § Alternativ als Kommandozeilentool $ pip install autopep8 Dokumentation: https://pypi.org/project/autopep8/ Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 24 Quellcode-Formatierer autopep8 Integration in Visual Studio Code { "[python]": { "editor.defaultFormatter": "ms-python.autopep8", "editor.formatOnSave": true } } Konfiguration [tool.autopep8] max_line_length = 120 indent_size = 2 Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 25 Mikroübung Richtig oder falsch? Œ Python ist eine statisch typisierte Programmiersprache  CPython ist die Referenzimplementierung von Python Ž Über virtuelle Umgebungen können Python-Pakete für unterschiedliche Projekte in unterschiedlichen Versionen installiert werden  Python-Pakete mit C-Erweiterungen erfordern zum Installieren stets das Vorhandensein eines C-Compilers  Visual Studio Code bietet über eine Erweiterung eine Unterstützung für die Erstellung von Python-Projekten ‘ Anweisungen müssen mit einem Semikolon abgeschlossen werden Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.1 Einleitung 26 Kapitel 2 Einführung in Python Œ Einleitung  Variablen, Datentypen und Operatoren Ž Kontrollstrukturen, Funktionen und Fehlerbehandlung  Module, Klassen und Typannotationen  Comprehensions, Iteratoren und Generatoren ‘ Standard-Bibliothek ’ Nebenläufige Programmierung Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) 27 Variablen Deklaration Variablen müssen vor ihrer Verwendung deklariert werden foo = 42 bar = foo / 2 Andernfalls kommt es zur Laufzeit zu einem NameError bar = foo / 2 # NameError: name 'foo' is not defined Konstanten Python bietet keine Syntax zur Definition von Konstanten. Per Konvention werden Variablen mit der Semantik einer Konstanten komplett großgeschrieben PI = 3.1415 Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 28 Variablen Spezieller Wert None Es kann zur Laufzeit nicht direkt geprüft werden, ob eine Variable definiert wurde. Es kann jedoch der spezielle Wert None hierzu genutzt werden: foo = None #... if foo is not None: print(foo) Explizites Löschen foo = 42 del foo print(foo) # NameError: name 'foo' is not defined Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 29 Variablen Gültigkeitsbereich Außerhalb von Funktionen und Klassen sind Variablen stets global - sie gelten in dem gesamten Modul (der Datei) if True: foo = 42 print(foo) # kein Fehler Variablennamen Konvention: Snake Case my_var = 42 Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 30 Datentypen Built-in-Typen im Überblick Klasse Werte Beispiel immutable int Ganze Zahlen 42 ja float Fließkommazahlen 42.21 ja complex Komplexe Zahlen 1+2j ja bool Wahrheitswerte True, False ja str Zeichenketten 'Foo', "Foo" ja tuple Tupel (1, 'foo') ja range Zahlenbereiche range(1, 10) ja list Listen [1, 'foo'] nein set Mengen {1, 'foo'} nein dict Assoziative Arrays {1: 'foo', 'bar': 42} nein § Die Datentypen str bis list sind Sequenztypen; deren Werte werden Sequenzen genannt § Bei den Datentypen str bis dict werden die Werte Container genannt Der Wert None gehört zur Klasse NoneType. Zu diesen und weiteren Build-in Types vgl. https://docs.python.org/3/library/index.html. Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 31 Datentypen Allgemeines Explizite Typumwandlung foo = 42 foo = '42' bar = 'Antwort: ' + str(foo) bar = int(foo) / 2 Führt zu einem ValueError, falls die Umwandlung nicht möglich ist Ermittlung/Überprüfung des Datentyps foo = 42 foo = 42 type(foo) # => isinstance(foo, int) # => True Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 32 Datentypen Boolesche Werte Jedes Objekt kann anstelle eines booleschen Wertes verwendet werden Ein Objekt gilt genau dann als wahr, falls weder seine Methode __bool__() den Wert False noch __len__() die Zahl 0 liefern foo = 'bar' if foo: print('wahr') Built-In-Objekte, die als unwahr gelten § Konstanten: False, None § Zahl 0 beliebigen numerischen Typs: 0, 0.0, Fraction(0, 1), etc. § Leere Sequenzen/Sammlungen: '', (), [], {}, etc. Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 33 Datentypen Zeichenketten Eine Zeichenkette (String) ist eine Sequenz von Unicode-Zeichen Begrenzung einzeiliger String-Literale 'Hello world' "Hello world" Escaping § Steuerzeichen: \n, \r, \t etc. (Newline, Carriage Return, Tabulator) § \', \", \\ (einfaches/doppeltes Anführungszeichen, Backslash) § Unicode Code Point, z. B. \u004D (16 bit) und \U0001D11E (32 bit) Raw-Zeichenketten Durch das Präfix r wird das Escaping weitgehend deaktiviert r'\section{Überschrift}' r"\section{Überschrift}" Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 34 Datentypen Zeichenketten: Formatierung Methode format x, y = 1/3, 2/3 print('({:.2f}, {:.2f})'.format(x, y)) # Ausgabe: (0.33, 0.67) Alternativen für den Zugriff auf die Argumente x, y = 1/3, 2/3 print('({0:.2f}, {1:.2f})'.format(x, y)) # Zugriff via Index print('({a:.2f}, {b:.2f})'.format(a=x, b=y)) # Zugriff via Namen Kurzschreibweise x, y = 1/3, 2/3 print(f'({x:.2f}, {y:.2f})') Zur Formatsspezifikation (Anzahl Nachkommastellen etc.) vgl. https://docs.python.org/3/library/string.html#formatspec Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 35 Datentypen Zeichenketten: Ausgewählte Operationen Ausdruck Erläuterung s.endswith(s2) True, falls s auf s2 endet s.find(s2) Index von s2 in s (-1, falls nicht vorhanden) s.join(x) Erzeugt eine Zeichenkette aus der Sequenz x von Zeichenketten mit s als Trenner s.lower() Liefert s in Kleinbuchstaben s.replace(old, new) Liefert s mit Ersetzungen von old durch new s.split(sep) Liefert eine Liste durch Zerlegung von s mit dem Trenner sep s.splitlines() Liefert eine Liste mit den Zeilen in s s.startswith(s2) True, falls s mit s2 beginnt s.strip() Liefert s mit entferntem Whitespace (Anfang & Ende) s.upper() Liefert s in Großbuchstaben Zu weiteren Operationen vgl. https://docs.python.org/3/library/string.html#module-string Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 36 Datentypen Listen Eine Liste ist eine Sequenz beliebiger Werte Merkmale § Die Reihenfolge, in der Werte hinzugefügt werden, bleibt erhalten § Kann denselben Wert mehrmals enthalten § Einfügen, Ersetzen und Löschen von Werten ist möglich Dies erfolgt am Ende der Liste deutlich performanter als z. B. am Anfang § Besitzt keinen konstanten Hashwert (ist nicht hashable) Kann daher nicht als Element in Mengen oder als Schlüssel in assoziativen Arrays verwendet werden Erstellen farben = ['rot', 'grün', 'blau'] zahlen = list(range(10)) # Neue Liste anhand eines iterierbaren Objekts Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 37 Datentypen Listen Länge einer Liste farben = ['rot', 'grün', 'blau', 'rot', 'grün', 'blau'] len(farben) # => 6 Zugriff auf ein Element über seinen Index farben # => 'rot' farben[-1] # => 'blau' Index eines Elements ermitteln farben.index('grün') # => 1 farben.index('grün', 3) # => 4 (ab Index 3) farben.index('grün', 2, 3) # => ValueError (2 True Wert hinten anfügen Wert einfügen farben = ['rot', 'grün'] farben = ['rot', 'blau'] farben.append('blau') farben.insert(1, 'grün') In beiden Fällen hat farben danach den Wert ['rot', 'grün', 'blau'] Wert entfernen farben.remove('rot') # entfernt das erste Auftreten des Wertes 'rot' farben.pop(0) # entfernt das Element mit Index 0 und liefert es zurück Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 39 Datentypen Listen Sortieren der Liste my_list = ['X', 'A', 'b'] my_list.sort() # my_list danach: ['A', 'X', 'b'] my_list.sort(key=str.lower) # my_list danach: ['A', 'b', 'X'] my_list.sort(reverse=True) # my_list danach: ['b', 'X', 'A'] Neue, sortierte Liste erzeugen sorted(my_list, key=str.lower) # => ['A', 'b', 'X'] Ein iterierbares Objekt ist eine Sequenz, ein Container (der Iteration unterstützt) oder ein Iterator-Objekt Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 40 Datentypen Tupel Ein Tupel ist eine unveränderbare Sequenz von Werten Merkmale § Die Reihenfolge der Werte bleibt erhalten § Kann denselben Wert mehrmals enthalten § Manipulationen (Einfügen, Ersetzen, Löschen) sind nicht möglich § Besitzt einen konstanten Hashwert (ist hashable) Kann daher Element einer Menge bzw. Schlüssel in einem assoziativen Arrays sein § Speichereffizienter als Listen Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 41 Datentypen Tupel Erstellen my_tuple1 = ('a',) # Ohne Komma wird ein String erzeugt my_tuple2 = ('a', 42) my_tuple3 = tuple([1, 2, 3]) # über ein iterierbares Objekt (hier: Liste) Operationen Die Klasse tuple unterstützt alle nicht-modifizierenden Operationen, die auch list unterstützt, z. B. farben = ('rot', 'grün', 'blau') farben # => 'rot' farben[-1] # => 'blau' Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 42 Datentypen Ranges Eine Range repräsentiert eine Sequenz von Zahlen Merkmale § Konstanter Speicherplatzbedarf unabhängig von der Länge der Sequenz § Manipulationen sind nicht möglich § Nutzung typischerweise in for-Schleifen Erstellen my_range1 = range(10) # von 0 bis 10 (exkl.) my_range2 = range(1, 11) # von 1 bis 11 (exkl.) my_range3 = range(0, 10, 3) # Werte 0, 3, 6 und 9 Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 43 Datentypen Mengen Eine Menge repräsentiert eine ungeordnete Sammlung von Werten Merkmale § Die Reihenfolge, in der Werte hinzugefügt werden, bleibt nicht erhalten § Jeder Wert kann nur einmal enthalten sein § Die Werte müssen unveränderbar sein (hashable) § Einfügen, Ersetzen und Löschen von Werten ist möglich § Besitzt keinen konstanten Hashwert (ist nicht hashable) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 44 Datentypen Mengen Erstellen my_set1 = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'} my_set2 = set([1, 2, 3]) # über ein iterierbares Objekt (hier: Liste) Anzahl Elemente farben = {'rot', 'grün', 'blau' } len(farben) # => 3 Prüfen, ob ein Element enthalten ist 'blau' in farben # => True Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 45 Datentypen Mengen Wert hinzufügen farben = {'rot', 'grün'} farben.add('blau') # farben danach: {'grün', 'rot', 'blau'} Mehrere Werte hinzufügen farben = {'rot'} farben.update(['grün', 'blau']) # farben danach: {'grün', 'rot', 'blau'} Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 46 Datentypen Mengen Wert entfernen farben = {'rot', 'grün', 'blau' } farben.remove('rot') # farben danach: {'grün', 'blau'} farben.remove('lila') # KeyError farben.discard('lila') # Kein KeyError Mehrere Werte entfernen farben = {'rot', 'grün', 'blau' } farben.difference_update(['rot', 'blau']) # farben danach: {'grün'} Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 47 Datentypen Mengen Ausgewählte Mengenoperationen s1, s2, s3 = {1, 2}, {1, 2, 3}, {3, 4} s1.isdisjoint(s2) # => False (Schnittmenge ist nicht leer) s2 & s3 # => {3} (Schnittmenge) s1 < s2 # => True (s1 ist eine echte Teilmenge von s2) s2 >= s1 # => True (s2 ist eine Obermenge von s1) s2 | s3 # => {1, 2, 3, 4} (Vereinigungsmenge) s2 ^ s3 # => {1, 2, 4} (Vereinigungsmenge ohne Schnittmenge) s2 - s3 # => {1, 2} (Elemente aus s2 ohne diejenigen aus s3) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 48 Datentypen Unveränderbare Mengen Mit frozenset steht eine unveränderbare Variante von set zur Verfügung farben = frozenset({'rot', 'grün', 'blau' }) # über ein iterierbares Objekt Die Klasse frozenset unterstützt alle nicht-modifizierenden Operationen, die auch set unterstützt, z. B. farben = frozenset({'rot', 'grün' }) | frozenset({'blau'}) # farben danach: frozenset({'grün', 'blau', 'rot'}) Ein frozenset-Objekt besitzt einen konstanten Hashwert und kann daher ein Element einer Menge bzw. ein Schlüssel eines assoziativen Arrays sein farbmengen = {frozenset({'rot', 'grün'}), frozenset({'grün', 'blau'})} Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 49 Datentypen Assoziative Arrays Ein assoziatives Array speichert Schlüssel-Wert-Paare Merkmale § Reihenfolge, in der Schlüssel-Wert-Paare hinzugefügt werden, bleibt erhalten § Jedes Schlüssel-Wert-Paar kann nur einmal enthalten sein § Die Schlüssel müssen unveränderbar sein (hashable) § Einfügen, Ersetzen und Löschen von Schlüssel-Wert-Paaren ist möglich § Besitzt keinen konstanten Hashwert (ist nicht hashable) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 50 Datentypen Assoziative Arrays Erstellen my_dict1 = {'one': 1, 'two': 2, 'three': 3} my_dict2 = dict([('one', 1), ('two', 2), ('three', 3)]) # Liste von Tupeln my_dict3 = dict(zip(['one', 'two', 'three'], [1, 2, 3])) Anzahl Schlüssel-Wert-Paare zahlen = {'one': 1, 'two': 2, 'three': 3} len(zahlen) # => 3 Wert zu einem Schlüssel ermitteln zahlen['one'] # => 1 zahlen['ten'] # KeyError zahlen.get('ten', 10) # => 10 (als Defaultwert) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 51 Datentypen Assoziative Arrays Schlüssel-Wert-Paar hinzufügen zahlen = {'one': 1, 'two': 2} zahlen['three'] = 3 # zahlen danach: {'one': 1, 'two': 2, 'three': 3} Mehrere Schlüssel-Wert-Paare hinzufügen zahlen = {'one': 1} zahlen.update({'two': 2, 'three': 3}) # zahlen danach: {'one': 1, 'two': 2, 'three': 3} Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 52 Datentypen Assoziative Arrays Schlüssel-Wert-Paar entfernen zahlen = {'one': 1, 'two': 2, 'three': 3} del zahlen['one'] # zahlen danach: {'two': 2, 'three': 3} del zahlen['ten'] # KeyError Schlüssel-Wert-Paar entfernen und Wert zurückliefern zahlen = {'one': 1, 'two': 2, 'three': 3} zahl1 = zahlen.pop('one') # zahlen danach: {'two': 2, 'three': 3} zahl2 = zahlen.pop('ten', 10) # kein KeyError (liefert den Default-Wert) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 53 Datentypen Gemeinsame Operationen bei Sequenzen Ausdruck Erläuterung x in s True, falls für ein Element y in s gilt: x == y x not in s True, falls für kein Element y in s gilt: x == y s + t Konkatenation von s und t s * n oder n * s n-fache Konkatenation von s mit sich selbst s[i] i-tes Element von s (bei 0 beginnend) s[i:j] Slicing: Ausschnitt aus s von Index i (inkl.) bis Index j (exkl.) s[i:j:k] Wie oben, jedoch mit Schrittweite k len(s) Anzahl Einträge in s min(s), max(s) Kleinster bzw. größter Eintrag in s s.index(x, i, j) Index des ersten Elements y in s mit x == y (zwischen i und j) s.count(x) Anzahl der Elemente y in s, für die gilt: x == y Nicht jeder Sequenztyp unterstützt alle Operationen Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 54 Datentypen Gemeinsame Operationen bei Sequenzen: Slicing Beispiele Elementbereiche jedes n-te Element 'Hello'[2:4] # => 'll' 'abcdefghi'[::2] # => 'acegi' 'Hello'[2:] # => 'llo' 'abcdefghi'[1::2] # => 'bdfh' 'Hello'[:2] # => 'He' 'abcdefghi'[:5:2] # => 'ace' 'abcdefghi'[1:5:2] # => 'bd' slice-Objekte Ein Slice kann als Objekt erstellt werden - hierzu existiert die Klasse slice s1 = slice(1) # stop 'abcdefghi'[s1] # => 'a' s2 = slice(0, 2) # start, stop 'abcdefghi'[s2] # => 'ab' s3 = slice(1, 5, 2) # start, stop, step 'abcdefghi'[s3] # => 'bd' Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 55 Datentypen Zusätzliche Operationen bei veränderlichen Sequenzen Ausdruck Erläuterung s[i] = x Ersetzt Element an der Stelle i durch x s[i:j:t] = t Ersetzt die angegebenen Elemente durch die Elemente aus der Sequenz t del s[i:j:k] Entfernt die angegebenen Elemente aus s s.append(x) Fügt x an das Ende von s an s.clear() Entfernt alle Elemente aus s s.copy() Erzeugt eine flache Kopie von s s.extend(t) oder Fügt alle Elemente von t hinten an s an s += t s *= n n-fache Konkatenation von s mit sich selbst s.insert(i, x) Fügt das Element x an der Stelle i der Sequenz s hinzu s.pop(i) Liefert das Element an der Stelle i und entfernt es aus der Liste (Default für i ist 0. Fehler, wenn das Element nicht vorhanden ist) s.remove(x) Entfernt das erste y aus s mit x == y (kein solches y → Fehler) s.reverse() Invertiert die Reihenfolge der Elemente Nicht jeder Sequenztyp unterstützt alle Operationen Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 56 Operatoren Überblick Kategorie Operatoren (Auswahl) Beispiele Zuweisungs- =, +=, -=, *=, /=, %=, := a = 42 Operatoren a += 1 Arithmetische +, -, *, /, //, **, % a = 3 + 4 Operatoren Bit-Operatoren ~, &, |, ^, a = 4 , True Überprüfen auf Identität foo = [1, 2] foo = [1, 2] bar = [1, 2] bar = [1, 2] foo is bar # => False foo is not bar # => True Mehrfachvergleiche foo = 42 0 0 42 and 'John' # => 'John' Logisches ODER Ergebnis ist der erste Operand, falls dieser als wahr ist, sonst der zweite 'John' or '' # => 'John' None or 'John' # => 'John' Logisches NICHT Ergebnis ist True, falls der Operand als unwahr gilt, sonst False not 0 # => True not 'John' # => False Beim logischen UND/ODER wird der zweite Operand nur dann ausgewertet, wenn er das Ergebnis ist (short-curcuit evaluation) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 59 Operatoren Besonderheiten Division Fließkommadivision Ganzzahlige Division 42 / 2 # => 21.0 42 // 2 # => 21 Kein Inkrement-/Dekrement-Operator Python kennt die Operatoren ++ und -- nicht Kein ternärer Operator, jedoch bedingte Ausdrücke foo = 42 bar = 'even' if foo % 2 == 0 else 'odd' Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.2 Variablen, Datentypen und Operatoren 60 Kapitel 2 Einführung in Python Œ Einleitung  Variablen, Datentypen und Operatoren Ž Kontrollstrukturen, Funktionen und Fehlerbehandlung  Module, Klassen und Typannotationen  Comprehensions, Iteratoren und Generatoren ‘ Standard-Bibliothek ’ Nebenläufige Programmierung Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) 61 Kontrollstrukturen Verzweigungen if if day in range(1, 6): print('weekday') elif day in (6, 7): print('weekend') else: print('invalid') elif und else sind optional Kurzschreibweise s = 'even' if n % 2 == 0 else 'odd' Es gibt kein switch in Python Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 62 Kontrollstrukturen Schleifen for while # Iterieren über einen Zahlenbereich i = 0 for i in range(10): while i < 10: print(i) print(i) # Iterieren über Zeichen i += 1 for c in 'abc': print(c) # Iterieren über die Werte einer Liste for i in ['red', 'green', 'blue']: print(i) # Iterieren über die Schlüssel eines assoziativen Arrays for k in {'name': 'John', 'age': 42}: print(k) Python unterstützt auch die bekannten Anweisungen break und continue Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 63 Funktionen Definition def add(x, y): return x + y Aufruf mit Positionsargumenten Aufruf mit Schlüsselwortargumenten add(3, 4) # => 7 add(x=3, y=4) # => 7 Mehrere Rückgabewerte def foo(): return 21, 42 x, y = foo() # x=21, y=42 Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 64 Funktionen Variablen Lokale Variablen Jede Variable, die auf der linken Seite einer Zuweisung innerhalb einer Funktion steht, ist eine lokale Variable und nur innerhalb der Funktion gültig def foo(): x = 3 # definiert eine lokale Variable print(x) # NameError: name 'x' is not defined Zugriff auf globale Variablen x, y = 3, 4 x, y = 3, 4 def foo(): def foo(): print(y) # okay global x x = 4 # lokale Variable x = 5 # globale Variable Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 65 Funktionen Innere Funktionen Funktionen können verschachtelt werden, wobei innere Funktionen auf Variablen der äußeren Funktion Zugriff haben def foo(): def foo(): x = 1 x = 1 def bar(): def bar(): return x nonlocal x x = 42 return bar() + 1 bar() return x foo() # => 2 foo() # => 42 Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 66 Funktionen Parameter Pflichtparameter def add(x, y): return x + y add(3) # add() missing 1 required positional argument: 'y' Optionale Parameter def foo(x, y=0, n=1): def foo(x, l=None): return (x + y) ** n l = [] if l is None else l l.append(x) foo(1) # => 1 return l foo(2, 3) # => 5 foo(2, n=3) # => 8 foo(3, [1, 2]) # => [1, 2, 3] foo(3) # => Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 67 Mikroübung Quellcodeanalyse Was gibt das folgende Programm aus? def foo(x, l=[]): l.append(x) return l print(foo(3)) print(foo(4)) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 68 Funktionen Parameter: Variable Anzahl Argumente (Tupel) Definition und Aufruf def foo(a, *b): def foo(a, *b, c): print(a, b) # b ist ein Tupel print(a, b, c) foo(3) # Ausgabe: 3 () foo(3, 4, 5, c=6) foo(3, 4, 5) # Ausgabe: 3 (4, 5) # Ausgabe: 3 (4, 5) 6 Nach dem *-Parameter müssen Schlüsselwortargumente verwendet werden Aufruf mit einer Liste l = [3, 4] foo(3, *l) Es darf nur einen *-Parameter geben Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 69 Funktionen Parameter: Variable Anzahl Argumente (assoz. Array) Definition und Aufruf def foo(a, **b): print(a, b) # b ist ein assoziatives Array foo(3) # Ausgabe: 3 {} foo(3, x=3, y=4) # Ausgabe: 3 {'x': 3, 'y': 4} Nach einem **-Parameter dürfen keine weiteren Parameter stehen Aufruf mit einem assoziativem Array d = {'a': 3, 'x': 4, 'y': 5} foo(**d) # Ausgabe: 3 {'x': 4, 'y': 5} Das assoziative Array muss für alle Pflichtparameter je einen Eintrag besitzten, sonst wird ein TypeError geworfen Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 70 Funktionen Funktionen als Werte Funktionen sind Objekte und können wie andere Objekte behandelt werden Zuweisung zu einer Variablen Funktion als Rückgabewert def add(x, y): def make_incrementor(v): return x + y def inc(x): foo = add nonlocal v foo(3, 4) # => 7 v += x return v Funktion als Argument return inc def add(x, y): f = make_incrementor(42) return x + y f(1) # => 43 def foo(f, x, y): f(1) # => 44 return f(x, y) foo(add, 3, 4) # => 7 Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 71 Funktionen Lambda-Ausdrücke Ein Lambda-Ausdruck erzeugt eine Funktion, die aus genau einem Ausdruck besteht Lambda-Ausdruck Äquivalente Funktion add = lambda x, y: x + y def add(x, y): add(3, 4) # => 7 return x + y add(3, 4) # => 7 Nutzen Lambda-Ausdrücke sind immer dann eine Alternative zu einer Funktion, wenn die Funktion nur aus einem Ausdruck besteht und nur einmal benötigt wird d = [{'name': 'John', 'age': 42}, {'name': 'Max', 'age': 21}] sorted(d, key=lambda x: x['age']) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 72 Funktionen Filter, Map und Reduce Elemente eines iterierbaren Objekts ausfiltern numbers = [1, 2, 3, 4] even_numbers_iter = filter(lambda x: x % 2 == 0, numbers) Parameter § Funktion, die für jedes Element des iterierbaren Objekts aufzurufen ist Wird None übergeben, dann werden alle als unwahr geltenen Elemente ausgefiltert § Iterierbares Objekt Rückgabewert Rückgabewert ist ein Iterator; aus diesem kann z. B. eine Liste erzeugt werden even_numbers = list(filter(lambda x: x % 2 == 0, numbers)) Iterierbare Objekte und Iteratoren werden später ausführlich behandelt Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 73 Funktionen Filter, Map und Reduce Elemente eines iterierbaren Objekts auf (andere) Elemente abbilden lowercase_words = list(map(lambda x: x.lower(), ['FOO', 'BAR', 'BAZ'])) Parameter § Funktion, die für jedes Element des iterierbaren Objekts aufzurufen ist § Ein oder mehrere iterierbare Objekte Die Funktion wird solange mit je einem Element pro iterierbaren Objekt aufgerufen, bis alle Elemente des kürzesten iterierbaren Objekts durchlaufen wurden Rückgabewert: Iterator Beispiel mit mehreren iterierbaren Objekten result = list(map(lambda x, y: x.lower() + y, 'ABC', '1234')) # result: ['a1', 'b2', 'c3'] Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 74 Funktionen Filter, Map und Reduce Elemente eines iterierbaren Objekts auf einen Wert reduzieren from functools import reduce total = reduce(lambda total, value: total + value, [1, 2, 3, 4]) # total: 10 Parameter § Funktion, die für jedes Element des iterierbaren Objekts aufzurufen ist § Ein iterierbares Objekt § Initialwert (optional) Per Default wird als Initialwert das erste Element des iterierbaren Objekts gewählt Beispiel mit explizitem Initialwert data = [('John', 42), ('Max', 20)] avg_age = reduce(lambda total, value: total + value, data, 0) / len(data) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 75 Fehlerbehandlung Auslösen von Exceptions Abfangen von Exceptions def gsum(x): try: if x < 0: result = gsum('3') raise ValueError('...') except TypeError: return x * (x + 1) // 2 print('Falscher Datentyp') except ValueError as e: print('Außerhalb des Wertebereichs', e) except: pass # nichts tun else: print(result) finally: print('Wird immer aufgerufen') Mehrere Ausnahmen gleichzeitig abfangen except (TypeError, ValueError) as err: Alle Exception-Klassen sind direkte oder indirekte Nachfahren der Klasse BaseException Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.3 Kontrollstrukturen, Funktionen und Fehlerbehandlung 76 Kapitel 2 Einführung in Python Œ Einleitung  Variablen, Datentypen und Operatoren Ž Kontrollstrukturen, Funktionen und Fehlerbehandlung  Module, Klassen und Typannotationen  Comprehensions, Iteratoren und Generatoren ‘ Standard-Bibliothek ’ Nebenläufige Programmierung Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) 77 Module Einleitung Ein Modul ist eine Datei, die Python-Definitionen und -Anweisungen enthält Dateinamenserweiterung ist.py Kennzeichen § Die Datei, die dem Interpreter zur Ausführung übergeben wird, ist das Hauptmodul § Die Anweisungen in einem Modul werden nur einmal ausgeführt beim ersten Import bzw. wenn das Modul dem Interpreter zur Ausführung übergeben wird § Alle Variablendefinitionen in einem Modul, die außerhalb von Klassen und Funktionen liegen, sind globale Variablen des Moduls Jedes Modul hat seinen eigenen Namensraum § Definitionen in einem Modul sind zunächst nur innerhalb des Moduls sichtbar - sie können jedoch in anderen Modulen importiert werden § Die Variable __name__ enthält den Modulnamen Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 78 Module Beispiel Modul 1 Modul 2 myapp ├── main.py myvar = 21 import mymodule1 ├── mymodule1.py myvar = 42 └── mymodule2.py def myfunc(): def myfunc(): print('mymodule1.myvar:', myvar) print('mymodule2.myvar:', myvar) print('inside module', __name__) print('inside module', __name__) mymodule1.myfunc() Hauptmodul Konsolenausgabe import mymodule2 inside module mymodule1 inside module mymodule2 print('inside module', __name__) mymodule1.myvar: 21 mymodule2.myfunc() inside module __main__ print(mymodule2.myvar) mymodule2.myvar: 42 42 Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 79 Module Import-Alternativen Import des gesamten Moduls Ohne Namensänderung Mit Namensänderung import mymodule1 import mymodule1 as foo mymodule1.myfunc() foo.myfunc() Importiert das Modul mymodule1 und stellt es als Modulobjekt (Klasse module) unter dem Namen mymodule1 bzw. foo bereit Alle Definitionen des Moduls stehen als gleichnamige Instanzattribute zur Verfügung. Import einzelner Definitionen des Moduls Ohne Namensänderung Mit Namensänderung from mymodule1 import myfunc, myvar from mymodule1 import myfunc as bar myfunc() bar() Die Anweisungen des Moduls werden weiterhin ausgeführt Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 80 Module Ausführen von Modulen als Skript Jedes Modul kann dem Interpreter zur Ausführung übergeben werden $ python mymodule1.py Auswirkungen § Die Anweisungen in dem Modul werden ausgeführt § Das Modul wird zum Hauptmodul Die Variable __name__ hat innerhalb des Moduls damit den Wert __main__ Anweisungen nur im Falle eines Hauptmoduls ausführen if __name__ == "__main__": print('Wird nur ausgeführt, wenn das Modul das Hauptmodul ist') Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 81 Module Auflösen von Modulnamen Ablauf: Laden eines Moduls X Achtung § Es wird zunächst nach einem Built-in-Modul X gesucht Eigene Module sollten nicht den gleichen Namen § Existiert dieses nicht, dann wird nacheinander in den Verzeichnissen aus der Liste besitzen wie Standard- Module, da die eigenen sys.path nach dem Modul gesucht Module dann nicht geladen werden können Einträge der Liste sys.path Œ Verzeichnis, welches das auszuführende Skript enthält  Einträge aus der Umgebungsvariablen PYTHONPATH (analog zu PATH) Ž Installationsabhängige Defaults Zugriff auf die Liste sys.path import sys print(sys.path) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 82 Module Caching und Neuladen von Modulen Caching von Modulen Um das Laden der Module zu beschleunigen, wird deren Bytecode im Unterverzeichnis __pycache__ abgelegt1 Automatisches Neuladen geänderter Module Nach dem Laden eines Moduls werden nachträgliche Änderungen vom Interpreter nicht erkannt; in JupyterLab kann jedoch das automatische Neuladen von Modulen aktiviert werden2 %load_ext autoreload %autoreload 2 Achtung: Bei einer Änderung eines Moduls und erneutem Import werden die Anweisungen im Modul erneut ausgeführt 1 Dies gilt nicht für das Hauptmodul. Zudem wird nur das Laden und nicht die Ausführung des Moduls beschleunigt. 2 Die beiden Kommandos sind sog. magische Kommandos (magic commands), die in JupyterLab (allg.: IPython) zur Verfügung stehen Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 83 Module Pakete Ein Paket (package) stellt einen Namensraum für Module bereit, sodass myapp Namenskonflikte zwischen Modulen unterschiedlicher Pakete vermieden werden ├── main.py └── mypackage ├── __init__.py Definition └── mysubpackage ├── __init__.py Ein Paket ist ein Verzeichnis mit einer Datei __init__.py ├── mymodule1.py └── mymodule2.py Diese kann leer sein oder Quellcode zur Initialisierung des Pakets enthalten Merkmale § Die Module eines Pakets sind Dateien in dem Paket-Verzeichnis § Ein Paket kann Subpakete (Unterverzeichnisse) enthalten Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 84 Module Pakete Vollständige Modulname myapp ├── main.py Der vollständige Modulname beinhaltet den Paketnamen, der ggf. wiederum den └── mypackage Namen des übergeordneten Pakets enthält ├── __init__.py └── mysubpackage z. B. mypackage.mysubpackage.mymodule1 ├── __init__.py ├── mymodule1.py └── mymodule2.py Import eines Moduls: Mit Paket-Präfix1 import mypackage.mysubpackage.mymodule1 mypackage.mysubpackage.mymodule1.myfunc() Import eines Moduls: Ohne Paket-Präfix from mypackage.mysubpackage import mymodule1 mymodule1.myfunc() 1 Der vollständige Modulname ist auch dann anzugeben, wenn das Modul von einem anderen Modul desselben Pakets importiert wird Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 85 Module Pakete Die bekannten Import-Alternativen sind auch beim Einsatz von Paketen möglich myapp ├── main.py └── mypackage Import eines Moduls unter anderem Namen ├── __init__.py └── mysubpackage import mypackage.mysubpackage.mymodule1 as mymod ├── __init__.py ├── mymodule1.py mymod.myfunc() └── mymodule2.py Import einzelner Definitionen eines Moduls Ohne Namensänderung from mypackage.mysubpackage.mymodule2 import myfunc myfunc() Mit Namensänderung from mypackage.mysubpackage.mymodule2 import myfunc as my_func my_func() Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 86 Klassen Definition Verwendung class Rectangle: # Instanziierung # Konstruktormethode r = Rectangle(2, 3) def __init__(self, width, height): self.width = width # Zugriff auf Instanzattribut self.height = height r.width # => 2 # Instanzmethode # Zugriff auf Instanzmethode def area(self): r.area() # => 6 return self.width * self.height # Alternative Methodenaufrufe Jeder Methode muss self als ersten Parameter Rectangle.area(r) # => 6 besitzen; darüber ist innerhalb der Methode die Instanz f = r.area referenzierbar f() # => 6 Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 87 Klassen Nicht-öffentliche Variablen und Methoden Python bietet keine Zugriffsmodifizierer, jedoch existieren entsprechende Namenskonventionen Ein Unterstrich als Präfix Zwei Unterstriche als Präfix class Foo: class Foo: def __init__(self, bar): def __init__(self, bar): self._bar = bar self.__bar = bar f = Foo('Bar') f = Foo('Bar') print(f._bar) # trotzdem möglich print(f._Foo__bar) # möglich print(f.__bar) # AttributeError Entspricht package in Java § Entspricht private in Java § Name __bar wird erweitert zu _Foo__bar, um Namenskonflikte bei Vererbung zu vermeiden Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 88 Klassen Klassenvariablen und -methoden Definition Verwendung class Foo: Foo.bar # => 21 bar = 21 # Klassenvariable Foo.baz() # => 42 __baz = 42 # priv. Klassenvariable # Über eine Instanz: @classmethod # Funktionsdekorator f = Foo() def baz(cls): f.bar # => 21 return cls.__baz f.baz() # => 42 Einsatzbereiche für Klassenmethoden § Erzeugung von Instanzen (Factory-Methoden) § Bereitstellung von Informationen über die Klasse (z. B. Anzahl Instanzen) § Testunterstützung Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 89 Klassen Statische Methoden Statische Methoden besitzen keinen Parameter, über den sie auf die Klasse Zugriff erhalten Definition Verwendung class Foo: Foo.bar() # => 42 @staticmethod # Funktionsdekorator # Über eine Instanz: def bar(): f = Foo() return 42 f.bar() # => 42 Einsatzbereich für statische Methoden Bereitstellung von Hilfsmethoden Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 90 Klassen Vererbung Definition einer Subklasse class Square(Rectangle): class Foo: def __init__(self, size): def foo(self): super().__init__(size, size) return 21 class Bar(Foo): def foo(self): return super().foo() * 2 § Ohne explizite Basisklasse wird implizit object angenommen § Mehrere Basisklassen (mit Komma getrennt) möglich → Mehrfachvererbung Nützliche Ausdrücke issubclass(Bar, Foo) # => True, falls Bar eine Subklasse von Foo ist MyClass.__bases__ # => Tupel der Basisklassen von MyClass Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 91 Klassen Abstrakte Klassen Definition Verwendung from abc import ABC, abstractmethod class Circle(Shape): def __init__(self, id): class Shape(ABC): super().__init__(id) def __init__(self, id): self.id = id def display(self): print('Circle:', self.id) @abstractmethod def display(self): pass Anmerkung Python besitzt kein dediziertes Sprachkonstrukt zur Definition von Interfaces Jedoch können abstrakte Klassen hierzu eingesetzt werden Analog zu @abstractmethod existieren die Dekoratoren @abstractclassmethod und @abstractstaticmethod Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 92 Klassen Properties class Text: foo = Text('foo') def __init__(self, content): self._content = content print(foo.content) # Ausgabe: foo @property def content(self): foo.content = 'bar' return self._content foo.content = 3 print(foo.content) @content.setter # Ausgabe: bar def content(self, content): if isinstance(content, str) and len(content) < 80: del foo.content self._content = content print(foo.content) # AttributeError @content.deleter def content(self): del self._content Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 93 Klassen Spezielle Methoden String-Repräsentation (informell) class Rectangle: #... def __str__(self): return f'Rechteck({self.width:.2f}, {self.height:.2f})' Wird z. B. von der Funktion print() aufgerufen String-Repräsentation (formell) class Rectangle: #... def __repr__(self): return f'Rectangle({self.width}, {self.height})' Sollte möglichst wie ein gültiger Python-Ausdruck aussehen Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 94 Klassen Spezielle Methoden Test auf Gleichheit (Implementierung des Operators ==) class Rectangle: #... def __eq__(self, other): return (self.width, self.height) == (other.width, other.height) Für !=, = existieren die Methoden __ne__(), __lt__(), __le__(), __gt__() und __ge__() Hashfunktion class Rectangle: #... def __hash__(self): return hash((self.width, self.height)) Die Methode __hash__ wird von der Built-in-Funktion hash() aufgerufen Zu diesen und weiteren speziellen Methoden vgl. https://docs.python.org/3/reference/datamodel.html#special-method-names Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 95 Klassen Spezielle Methoden Überladen numerischer Operatoren class Vector: v1 = Vector(1, 2) def __init__(self, x, y): v2 = Vector(3, 4) self.x = x v3 = v1 + v2 self.y = y def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) Zu weiteren Methoden vgl. https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 96 Klassen Datenklassen Zu den speziellen Methoden können Implementierungen generiert werden Mutable Version Immutable Version from dataclasses import dataclass from dataclasses import dataclass @dataclass() @dataclass(frozen=True) class Rectangle: class Rectangle: width: float # Typannotation width: float = 0 # Defaultwert height: float height: float = 0 r1 = Rectangle(3, 4) r1 = Rectangle(3, 4) r1 == Rectangle(3, 4) # => True r2 = Rectangle() # kein Fehler r2 = Rectangle() # Fehler s = {r1} # kein Fehler s = {r1} # Fehler, da unhashable r1.width = 3 # Fehler Hierzu sind Typannotationen erforderlich Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 97 Mikroübung Fehlersuche class Sum: def __init__(x, y): self.x = x self.y = y def evaluate(): r = 0 for i in range(self.x, self.y) r += i return r s = new Sum(1, 4) print('Summe:', s.evaluate()) # Ergebnis soll 10 sein Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 98 Typannotationen Motivation Quellcode-Analyse Was gibt dieses Programm auf der Konsole aus? FAKTOR = 3 def berechneGesamtwert(grundwert): zusatzwert = grundwert * FAKTOR return grundwert + zusatzwert grundwert = "100" # Eingabe via UI gesamtwert = berechneGesamtwert(grundwert) print("Gesamtwert:", gesamtwert) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 99 Typannotationen Motivation Ergänzung um eine Typannotation def berechneGesamtwert(grundwert: float) -> float: #... Wirkung der Ergänzung Bei Verwendung des statischen Typüberprüfers mypy führt der Aufruf berechneGesamtwert("100") zur Entwicklungszeit zur Fehlermeldung Argument 1 to "berechneGesamtwert" has incompatible type "str"; expected "float" Dokumentation https://typing.readthedocs.io/en/latest/index.html Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 100 Typannotationen Statische Typüberprüfung mit mypy Der statische Typüberprüfer mypy1 ermöglicht es, auf Basis von Typannotationen Typfehler schon zur Entwicklungszeit festzustellen Installation Aufruf $ pip install mypy $ mypy program.py Integration in Visual Studio Code § Installation der Erweiterung Mypy Type Checker https://marketplace.visualstudio.com/items?itemName=ms-python.mypy-type-checker § Die statische Typüberprüfung wird per Default bei jedem Speichervorgang durchgeführt 1 http://mypy-lang.org Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 101 Typannotationen Syntax Als Typen können Built-in-Klassen1, benutzerdefinierte Klassen und Typen des typing-Moduls verwendet werden Built-in-Klassen1 vorname: str = 'John' daten: list = [1, 2, 3] Benutzerdefinierte Klassen class Rectangle: def __init__(self, width, height): self.width = width self.height = height #... r: Rectangle = Rectangle(2, 3) 1 Typische Built-in-Klassen sind int, float, complex, bool, str, tuple, range, list, set, dict Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 102 Typannotationen Syntax Elemente von Containern typisieren Listen Tupel users: list[str] = [ user: tuple[str, int] = ( "John", "Jane" "John", 42 ] ) Assoziative Arrays Mengen users: dict[int, str] = { users: set[tuple[str, int]] = { 1: "John", 2: "Jane" ("John", 42), ("Jane", 21) } } Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 103 Typannotationen Syntax Union-Typen values: set[int | str] = {"foo", 42, "bar"} Optionale Werte from typing import Optional value: Optional[str] = None # Abkürzung für str | None Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 104 Typannotationen Syntax Typannotationen innerhalb von Klassen from typing import ClassVar Ohne Typannotationen class Starship: class Starship: captain = 'Picard' stats = {} captain: str = 'Picard' damage: int def __init__(self, damage, captain=None): stats: ClassVar[dict[str, int]] = {} self.damage = damage if captain: def __init__(self, damage: int, captain: str | None = None): self.captain = captain self.damage = damage def hit(self): if captain: Starship.stats['hits'] = \ self.captain = captain # else: keep the default Starship.stats.get('hits', 0) + 1 def hit(self): Starship.stats['hits'] = Starship.stats.get('hits', 0) + 1 Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.4 Module, Klassen und Typannotationen 105 Kapitel 2 Einführung in Python Œ Einleitung  Variablen, Datentypen und Operatoren Ž Kontrollstrukturen, Funktionen und Fehlerbehandlung  Module, Klassen und Typannotationen  Comprehensions, Iteratoren und Generatoren ‘ Standard-Bibliothek ’ Nebenläufige Programmierung Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) 106 Comprehensions List Comprehensions Eine List Comprehension erstellt eine Liste auf Basis einer/mehrerer Sequenzen Transformation von Werten (mit Filterung) [(x, x * x) for x in range(4)] # => [(0, 0), (1, 1), (2, 4), (3, 9)] [(x, x * x) for x in range(4) if x % 2 == 0] # => [(0, 0), (2, 4)] Mehrere Input-Sequenzen [a + b for a in ('x', 'y') for b in ('0', '1')] # => ['x0', 'x1', 'y0', 'y1'] Verschachtelung [[j * j + i for j in range(2)] for i in range(10, 12)] # => [[10, 11], [11, 12]] Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.5 Comprehensions, Iteratoren und Generatoren 107 Comprehensions Weitere Comprehensions Set Comprehensions names = ['John', 'BOB', 'alice', 'john', 'j', 'Bob'] {n.capitalize() for n in names if len(n) > 1} # => {'John', 'Bob', 'Alice'} Reihenfolge ist nicht definiert, da ein set-Objekt eine ungeordnete Menge ist Dict Comprehensions colors = {'r': 'red', 'g': 'green', 'b': 'blue'} {k.upper(): colors.get(k) for k in colors} # => {'R': 'red', 'G': 'green', 'B': 'blue'} Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.5 Comprehensions, Iteratoren und Generatoren 108 Iteratoren Iterator-Objekt Ein Iterator-Objekt ist ein zustandsbehaftetes Objekt, das ein einheitliches Iterieren über eine Datenstruktur ermöglicht § Hierzu implementiert es die Methode __next__(), die bei jedem Aufruf das nächste Element der Datenstruktur liefert bzw. eine StopIteration-Exception wirft, falls kein Element mehr vorhanden ist § Die Built-in-Funktion next(obj) ruft obj.__next__() auf Iterierbares Objekt Ein iterierbares Objekt ist ein Objekt, das ein Iterator-Objekt bereitstellt (typischerweise zum Iterieren über eigene Elemente) § Hierzu implementiert es die Methode __iter__(), die ein Iterator-Objekt liefert § Die Built-in-Funktion iter(obj) ruft obj.__iter__() auf Die vorgestellten Sequenztypen sind iterierbare Objekte Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.5 Comprehensions, Iteratoren und Generatoren 109 Iteratoren Iterieren Iterieren mit der for-Schleife for element in [1, 2, 3]: print(element) Manuelles Iterieren Mit Default-Wert Mit Exception-Handling it = iter([1, 2, 3]) it = iter([1, 2, 3]) try: while (value := next(it, None)) is not None: while True: print(value) value = next(it) print(value) except StopIteration: pass Das 2. Argument von next() ist ein Default-Wert, der am Ende der Iteration geliefert wird, sodass keine StopIteration-Exception geworfen wird. Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.5 Comprehensions, Iteratoren und Generatoren 110 Iteratoren Eigener Iterator: Beispiel class Reverse: class Iter: def __init__(self, data): self.data = data self.index = len(data) def __next__(self): if self.index == 0: raise StopIteration self.index -= 1 return self.data[self.index] def __init__(self, data): self.data = data def __iter__(self): return self.Iter(self.data) Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.5 Comprehensions, Iteratoren und Generatoren 111 Iteratoren Modul itertools Über das Modul itertools der Standardbibliothek von Python werden hilfreiche Funktionen zur Erzeugung von Iteratoren geboten import itertools Verketten iterierbarer Objekte it = itertools.chain([1, 2, 3], ['A', 'B', 'C']) print(list(it)) # [1, 2, 3, 'A', 'B', 'C'] Die iterierbaren Objekte können auch durch ein iterierbares Objekt übergeben werden it = itertools.chain.from_iterable([[1, 2, 3], "ABC"]) print(list(it)) # [1, 2, 3, 'A', 'B', 'C'] Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.5 Comprehensions, Iteratoren und Generatoren 112 Iteratoren Modul itertools Partialsummen, Partialprodukte etc. it = itertools.accumulate([1, 2, 3, 4, 5]) print(list(it)) # [1, 3, 6, 10, 15] Der anzuwendende Operator kann auch explizit angegeben werden import operator it = itertools.accumulate([1, 2, 3, 4, 5], operator.mul) print(list(it)) # [1, 2, 6, 24, 120] Der Operator kann zudem durch einen Lambda-Ausdruck angegeben werden it = itertools.accumulate([1, 2, 3, 4, 5], lambda erg, val: erg * val) print(list(it)) # [1, 2, 6, 24, 120] Prof. Dr. Norman Lahme-Hütig | Software Engineering II (2024/25) | 2 Einführung in Python ▸ 2.5 Comprehensions, Iteratoren und Generatoren 113 Iteratoren Modul itertools Wiederholen von Werten it = itertools.repeat(42, 3) print(list(it)) # [42, 42, 42] Kartesisches Produkt it = itertools.product([1, 2, 3], "AB") print(list(it)) # [(1, 'A'), (1, 'B'), (2, 'A'), (2, 'B'), (3, 'A'), (3, 'B')] Es kann auch das n-fache kartesische Produkt eines iterierbaren Objekts mit sich selbst ermittelt werden, ohne es n mal übergeben zu müssen

Use Quizgecko on...
Browser
Browser