{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Was ist neu in Python 3.10\n", "\n", "
\n", "\n", "**Siehe auch:**\n", "\n", "* [What’s New In Python 3.10](https://docs.python.org/3.10/whatsnew/3.10.html)\n", "
" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [], "source": [ "import sys\n", "\n", "\n", "assert sys.version_info[:2] >= (3, 10)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Bessere Fehlermeldungen" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Syntaxfehler\n", "\n", "* Beim Parsen von Code, der nicht geschlossene Klammern enthält, schließt der Interpreter jetzt die Position der nicht geschlossenen Klammer oder Klammern ein, anstatt `SyntaxError: unexpected EOF` anzuzeigen.\n", "* Vom Interpreter ausgelöste `SyntaxError`-Ausnahmen heben nun den gesamten Fehlerbereich des Ausdrucks hervor, in dem der Syntaxfehler besteht, anstatt nur die Stelle, an der das Problem erkannt wird.\n", "* Es wurden spezialisierte Meldungen für `SyntaxError`-Ausnahmen hinzugefügt, z.B. für\n", "\n", " * fehlende `:` vor Blöcken\n", " * nicht eingeklammerte Tupel in Comprehensions\n", " * fehlende Kommas in Auflistungsliteralen und zwischen Ausdrücken\n", " * fehlende `:` und Werte in Dictionary-Literalen\n", " * Verwendung von `=` anstelle von `==` in Vergleichen\n", " * Verwendung von `*` in f-strings" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Einrückungsfehler\n", "\n", "* Viele `IndentationError` haben jetzt mehr Kontext." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Attribut-Fehler\n", "\n", "* `AttributeError` bieten nun Vorschläge für ähnliche Attributnamen in dem Objekt, von dem die Ausnahme ausgelöst wurde." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Name-Fehler\n", "\n", "* `NameError` bietet Vorschläge für ähnliche Variablennamen in der Funktion, von der aus die Ausnahme ausgelöst wurde." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Strukturelles Pattern-Matching\n", "\n", "Viele funktionale Sprachen haben einen `match`-Ausdruck, z.B. [Scala](https://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html), [Rust](https://doc.rust-lang.org/reference/expressions/match-expr.html), [F#](https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching).\n", "\n", "Eine `match`-Anweisung nimmt einen Ausdruck und vergleicht ihn mit aufeinanderfolgenden Mustern, die als ein oder mehrere Fälle angegeben sind. Dies ist oberflächlich gesehen ähnlich wie eine switch-Anweisung in C, Java oder JavaScript, aber viel mächtiger." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `match`\n", "\n", "Die einfachste Form vergleicht einen Wert mit einem oder mehreren Literalen:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def http_error(status):\n", " match status:\n", " case 400:\n", " return \"Bad request\"\n", " case 401:\n", " return \"Unauthorized\"\n", " case 403:\n", " return \"Forbidden\"\n", " case 404:\n", " return \"Not found\"\n", " case 418:\n", " return \"I’m a teapot\"\n", " case _:\n", " return \"Something else\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Bemerkung:**\n", "\n", "Nur in diesem Fall fungiert `_` als Platzhalter, der nie versagt, und **nicht** als Variablenname.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die Fälle prüfen nicht nur auf Gleichheit, sondern binden Variablen neu, die dem angegebenen Muster entsprechen. Zum Beispiel:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "not found\n", "Current value of NOT_FOUND=200\n" ] } ], "source": [ "NOT_FOUND = 404\n", "retcode = 200\n", "\n", "match retcode:\n", " case NOT_FOUND:\n", " print(\"not found\")\n", "\n", "print(f\"Current value of {NOT_FOUND=}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> »Wenn diese schlecht durchdachte Funktion wirklich zu Python hinzugefügt wird, verlieren wir ein Prinzip, das ich meinen Studenten immer beigebracht habe: ›Wenn du eine undokumentierte Konstante siehst, kannst du sie immer benennen, ohne die Bedeutung des Codes zu verändern.‹ Das algebraische Substitutionsprinzip? Es gilt dann nicht mehr.« – [Brandon Rhodes](https://x.com/brandon_rhodes/status/1360226108399099909)\n", "\n", "> «… die Semantik kann ganz anders sein als bei switch. Die Cases prüfen nicht einfach die Gleichheit, sondern binden Variablen neu, die mit dem angegebenen Muster übereinstimmen.» – [Jake VanderPlas](https://x.com/jakevdp/status/1359870794877132810)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Symbolische Konstanten\n", "\n", "Muster können benannte Konstanten verwenden. Diese müssen Dotted Names sein, damit sie nicht als Capture-Variable interpretiert werden können:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I’m feeling the blues :(\n" ] } ], "source": [ "from enum import Enum\n", "\n", "\n", "class Color(Enum):\n", " RED = 0\n", " GREEN = 1\n", " BLUE = 2\n", "\n", "\n", "color = Color(2)\n", "\n", "match color:\n", " case color.RED:\n", " print(\"I see red!\")\n", " case color.GREEN:\n", " print(\"Grass is green\")\n", " case color.BLUE:\n", " print(\"I’m feeling the blues :(\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> »… \"case CONSTANT\" passt eigentlich immer und wird einer Variablen namens CONSTANT zugewiesen« – [Armin Ronacher](https://x.com/mitsuhiko/status/1359263136994516999)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Siehe auch:**\n", "\n", "* [Structural pattern matching for Python](https://lwn.net/Articles/827179/)\n", "* [PEP 622 – Structural Pattern Matching](https://peps.python.org/pep-0622) wurde ersetzt durch\n", "\n", " * [PEP 634: Specification](https://peps.python.org/pep-0634)\n", " * [PEP 635: Motivation and Rationale](https://peps.python.org/pep-0635)\n", " * [PEP 636: Tutorial](https://peps.python.org/pep-0636)\n", "\n", "* [github.com/gvanrossum/patma/](https://github.com/gvanrossum/patma/)\n", "* [playground-622.ipynb on binder](https://mybinder.org/v2/gh/gvanrossum/patma/master?urlpath=lab/tree/playground-622.ipynb)\n", "* [Tobias Kohn: On the Syntax of Pattern Matching in Python](https://tobiaskohn.ch/index.php/2018/09/18/pattern-matching-syntax-in-python/)\n", "
" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.11 Kernel", "language": "python", "name": "python311" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.4" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }