{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Was ist neu in Python 3.9?\n", "\n", "Mit Python 3.9 wird erstmals ein neuer Release-Zyklus verwendet: zukünftig sollen jährlich neue Releases erscheinen (s.a. [PEP 602](https://peps.python.org/pep-0602/)). Die Entwickler\\*innen erhoffen sich hiervon u.a. schnellere Rückmeldungen zu neuen Features.\n", "\n", "Mit dem ersten veröffentlichten Release-Kandidaten soll Python auch eine stabile Binärschnittstelle (engl. *application binary interface,* ABI) erhalten: es soll nun keine ABI-Änderungen mehr in der 3.9-Reihe geben womit Erweiterungsmodule nicht mehr für jede Version neu kompiliert werden müssen.\n", "\n", "Weitere Informationen erhaltet ihr in [What’s New In Python 3.9](https://docs.python.org/3.9/whatsnew/3.9.html).\n", "\n", "Im Folgenden gebe ich Euch einen kurzen Überblick über einige der neuen Features." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installation\n", "\n", "### Überprüfen" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Python 3.9.0rc1\r\n" ] } ], "source": [ "!python3 -V" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "or" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import sys\n", "\n", "\n", "assert sys.version_info[:2] >= (3, 9)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## [PEP 584](https://peps.python.org/pep-0584): Dictionary Merge- und Update-Operatoren\n", "\n", "Für die built-in [dict](https://docs.python.org/3.9/library/stdtypes.html#dict)-Klasse gibt es nun ähnliche Operatoren wie zum Verketten von Listen: Merge (`|`) und Update (`|=`). Damit werden verschiedene Nachteile der bisherigen Methoden `dict.update`, `{**d1, **d2}` und `collections.ChainMap` beseitigt. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Beispiel [ipykernel/ipykernel/kernelapp.py](https://github.com/ipython/ipykernel/blob/main/ipykernel/kernelapp.py)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from IPython.core.application import ( # type:ignore[attr-defined]\n", " BaseIPythonApplication,\n", " base_aliases,\n", " base_flags,\n", " catch_config_error,\n", ")\n", "\n", "\n", "kernel_aliases = dict(base_aliases)\n", "kernel_aliases.update(\n", " {\n", " \"ip\": \"IPKernelApp.ip\",\n", " \"hb\": \"IPKernelApp.hb_port\",\n", " \"shell\": \"IPKernelApp.shell_port\",\n", " \"iopub\": \"IPKernelApp.iopub_port\",\n", " \"stdin\": \"IPKernelApp.stdin_port\",\n", " \"control\": \"IPKernelApp.control_port\",\n", " \"f\": \"IPKernelApp.connection_file\",\n", " \"transport\": \"IPKernelApp.transport\",\n", " }\n", ")\n", "\n", "kernel_flags = dict(base_flags)\n", "kernel_flags.update(\n", " {\n", " \"no-stdout\": (\n", " {\"IPKernelApp\": {\"no_stdout\": True}},\n", " \"redirect stdout to the null device\",\n", " ),\n", " \"no-stderr\": (\n", " {\"IPKernelApp\": {\"no_stderr\": True}},\n", " \"redirect stderr to the null device\",\n", " ),\n", " \"pylab\": (\n", " {\"IPKernelApp\": {\"pylab\": \"auto\"}},\n", " \"\"\"Pre-load matplotlib and numpy for interactive use with\n", " the default matplotlib backend.\"\"\",\n", " ),\n", " \"trio-loop\": (\n", " {\"InteractiveShell\": {\"trio_loop\": False}},\n", " \"Enable Trio as main event loop.\",\n", " ),\n", " }\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "kann vereinfacht werden mit:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "kernel_aliases = base_aliases | {\n", " \"ip\": \"KernelApp.ip\",\n", " \"hb\": \"KernelApp.hb_port\",\n", " \"shell\": \"KernelApp.shell_port\",\n", " \"iopub\": \"KernelApp.iopub_port\",\n", " \"stdin\": \"KernelApp.stdin_port\",\n", " \"parent\": \"KernelApp.parent\",\n", "}\n", "if sys.platform.startswith(\"win\"):\n", " kernel_aliases[\"interrupt\"] = \"KernelApp.interrupt\"\n", "\n", "kernel_flags = base_flags | {\n", " \"no-stdout\": (\n", " {\"KernelApp\": {\"no_stdout\": True}},\n", " \"stdout auf das Nullgerät umleiten\",\n", " ),\n", " \"no-stderr\": (\n", " {\"KernelApp\": {\"no_stderr\": True}},\n", " \"stderr auf das Nullgerät umleiten\",\n", " ),\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Beispiel [matplotlib/legend.py](https://github.com/matplotlib/matplotlib/blob/main/lib/matplotlib/legend.py)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hm = default_handler_map.copy()\n", "hm.update(self._custom_handler_map)\n", "return hm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "kann vereinfacht werden mit:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "return default_handler_map | self._handler_map" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## [PEP 616](https://peps.python.org/pep-0616): `removeprefix()` und `removesuffix()` für String-Methoden\n", "\n", "Mit [str.removeprefix(prefix)](https://docs.python.org/3.9/library/stdtypes.html#str.removeprefix) und [str.removesuffix(suffix)](https://docs.python.org/3.9/library/stdtypes.html#str.removesuffix) lassen sich nun einfach Präfixe und Suffixe entfernen. Auch für `bytes`, `bytearray`-Objekte und `collections.UserString`-Zeichenketten wurden ähnliche Methoden hinzugefügt. Insgesamt soll dies zu weniger zerbrechlichem, performanterem und besser lesbarem Code führen." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Beispiel [find_recursionlimit.py](https://github.com/python/cpython/blob/3.9/Tools/scripts/find_recursionlimit.py)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if test_func_name.startswith(\"test_\"):\n", " print(test_func_name[5:])\n", "else:\n", " print(test_func_name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "kann vereinfacht werden mit:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print (test_func_name.removeprefix (\"test_\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Beispiel [deccheck.py](https://github.com/python/cpython/blob/main/Modules/_decimal/tests/deccheck.py)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if funcname.startswith(\"context.\"):\n", " self.funcname = funcname.replace(\"context.\", \"\")\n", " self.contextfunc = True\n", "else:\n", " self.funcname = funcname" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "kann vereinfacht werden mit:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "self.contextfunc = funcname.startswith (\"context.\")\n", "self.funcname = funcname.removeprefix (\"context.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## [PEP 585](https://peps.python.org/pep-0585): Zusätzliche generische Typen\n", "\n", "In *Type Annotations* können nun z.B. `list` oder `dict` als generische Typen direkt verwendet werden – sie müssen nicht mehr extra aus `typing` importiert werden. Das Importieren von `typing` ist damit *deprecated*." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Beispiel" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def greet_all(names: list[str]) -> None:\n", " for name in names:\n", " print(\"Hello\", name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## [PEP 617](https://peps.python.org/pep-0617): Neuer PEG-Parser\n", "\n", "Python 3.9 verwendet nun einen [PEG](https://en.wikipedia.org/wiki/Parsing_expression_grammar) (Parsing Expression Grammar)-Parser anstelle des bisherigen [LL](https://de.wikipedia.org/wiki/LL-Parser)-Parser. Dies hat u.a. folgende Vorteile:\n", "\n", "* das Parsen abstrakter Syntaxbäume (engl. Abstract Syntax Trees, AST) vereinfacht sich erheblich\n", "* [Left recursion](https://en.wikipedia.org/wiki/Left_recursion) wird möglich\n", "* Das Erstellen konkreter Syntaxbäume (engl. Concrete Syntax Trees, CST) wird möglich\n", "\n", "Der neue Parser ist damit flexibler und soll vor allem beim Entwerfen neuer Sprachfunktionen genutzt werden. Das [ast](https://docs.python.org/3.9/library/ast.html#module-ast)-Modul verwendet den neuen Parser schon jetzt, ohne dass sich an der Ausgabe etwas geändert hätte.\n", "\n", "In Python 3.10 wird der alte Parser und alle davon abhängigen Funktionen – hauptsächlich das veraltete [parser](https://docs.python.org/3.9/library/parser.html#module-parser)-Modul – gelöscht. Nur in Python 3.9 könnt ihr auf der Kommandozeile mit `-X oldparser` oder mit der Umgebungsvariable `PYTHONOLDPARSER=1` zum LL-Parser zurückkehren." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## [PEP 615](https://peps.python.org/pep-0615): Unterstützung für die IANA-Zeitzonendatenbank in der Standardbibliothek\n", "\n", "Das neue [zoneinfo](https://docs.python.org/3.9/library/zoneinfo.html#module-zoneinfo)-Standardmodul bringt Unterstützung für die IANA-Zeitzonendatenbank in die Standardbibliothek." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "from datetime import datetime, timedelta\n", "from zoneinfo import ZoneInfo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pacific Daylight Time:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2020-10-31 12:00:00-07:00\n" ] } ], "source": [ "dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo(\"America/Los_Angeles\"))\n", "print(dt)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'PDT'" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dt.tzname()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pacific Standard Time:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2020-11-07 12:00:00-08:00\n" ] } ], "source": [ "dt += timedelta(days=7)\n", "print(dt)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "PST\n" ] } ], "source": [ "print(dt.tzname())" ] } ], "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 }