From 2dfe3da941ea5d0be8102eaceb77f12c37991869 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Thu, 3 Nov 2022 06:10:02 +0100 Subject: Update notebooks/python/python_3_8_to_3_11.ipynb and notebooks/python/python_oo.ipynb --- notebooks/python/input_file.dat | 0 notebooks/python/python_3_8_to_3_11.ipynb | 619 ++++++++++++++++++++++++++++++ notebooks/python/python_3_8to_3_11.ipynb | 64 --- notebooks/python/python_oo.ipynb | 4 +- 4 files changed, 622 insertions(+), 65 deletions(-) create mode 100644 notebooks/python/input_file.dat create mode 100644 notebooks/python/python_3_8_to_3_11.ipynb delete mode 100644 notebooks/python/python_3_8to_3_11.ipynb diff --git a/notebooks/python/input_file.dat b/notebooks/python/input_file.dat new file mode 100644 index 0000000..e69de29 diff --git a/notebooks/python/python_3_8_to_3_11.ipynb b/notebooks/python/python_3_8_to_3_11.ipynb new file mode 100644 index 0000000..52d5630 --- /dev/null +++ b/notebooks/python/python_3_8_to_3_11.ipynb @@ -0,0 +1,619 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "95c6942c-cd6a-437f-a35e-f6bbaf3555bd", + "metadata": {}, + "source": [ + "# A very brief summary of changes introduced in Python 3.8, 3.9, 3.10 and 3.11\n" + ] + }, + { + "cell_type": "markdown", + "id": "b3f102cb-0f33-43ad-a808-e8f3c171b370", + "metadata": {}, + "source": [ + "# Python 3.8\n", + "\n", + "Released on October 14th, 2019.\n", + "\n", + "\n", + "## Highlights\n", + "\n", + "- **PEP 572** – Assignment Expressions - The \"walrus operator\"\n", + "\n", + "- **PEP 570** – Python Positional-Only Parameters\n", + "\n", + "- **PEP 574** – Pickle protocol 5 with out-of-band data - aims to make `pickle` usable in a way where large data is handled as a separate stream of zero-copy buffers, letting the application handle those buffers optimally.\n", + "\n", + "- f-strings support = for self-documenting expressions and debugging" + ] + }, + { + "cell_type": "code", + "execution_count": 226, + "id": "a21e461a-8a7c-49d2-8a53-ab63ff2488bb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "List is too long (6 elements, expected <= 10)\n", + "List is too long (6 elements, expected <= 10)\n", + "my_list[3]='Eric'\n", + "my_list[4]='Terry J'\n", + "my_list[5]=Michael\n" + ] + } + ], + "source": [ + "# The walrus operator:\n", + "\n", + "my_list = [\"Greham\", \"John\", \"Terry G\", \"Eric\", \"Terry J\", \"Michael\"]\n", + "\n", + "# Python < 3.8\n", + "list_length = len(my_list)\n", + "if list_length > 5:\n", + " print(f\"List is too long ({list_length} elements, expected <= 10)\")\n", + "\n", + "# while using the walrus operator...\n", + "if (list_length := len(my_list)) > 5:\n", + " print(f\"List is too long ({list_length} elements, expected <= 10)\")\n", + "\n", + "\n", + "# f-strings support for self-documenting expressions and debugging using =\n", + "print(f\"{my_list[3]=!r}\")\n", + "print(f\"{my_list[4]=}\") # !r is implicit\n", + "print(f\"{my_list[5]=!s}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 227, + "id": "99b75989-e991-4f77-a62e-01776f5b606c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10 20 {'a': 1, 'b': 2, 'c': 3}\n" + ] + } + ], + "source": [ + "# Positional only parameters:\n", + "# def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):\n", + "# ----------- ---------- ----------\n", + "# | | |\n", + "# | Positional or keyword |\n", + "# | - Keyword only\n", + "# -- Positional only\n", + "\n", + "# Positional-only parameters give more control to library authors to better\n", + "# express the intended usage of an API and allows the API to evolve in a safe, backward-compatible way.\n", + "# Additionally, it makes the Python language more consistent with existing documentation and\n", + "# the behavior of various “builtin” and standard library functions.\n", + "\n", + "# One use case for this notation is that it allows pure Python functions to fully emulate behaviors of existing C coded functions.\n", + "# For example, the built-in divmod() function does not accept keyword arguments:\n", + "def divmod(a, b, /):\n", + " \"\"\"Emulate the built in divmod() function\"\"\"\n", + " return (a // b, a % b)\n", + "\n", + "# Another use case is to preclude keyword arguments when the parameter name is not helpful.\n", + "# For example, the builtin len() function has the signature len(obj, /).\n", + "# This precludes awkward calls such as: len(obj=\"hello\"), where the \"obj\" keyword argument impairs readability.\n", + "\n", + "# A further benefit of marking a parameter as positional-only is that it allows the parameter name to be changed in the future without risk of breaking client code.\n", + "\n", + "def my_func(a, b, /, **kwargs):\n", + " print(a, b, kwargs)\n", + "my_func(10, 20, a=1, b=2, c=3)" + ] + }, + { + "cell_type": "markdown", + "id": "1801f5cb-6620-43c9-a1c8-1ada25b046bf", + "metadata": {}, + "source": [ + "## Other changes\n", + "\n", + "- `continue` can be used in the `finally` clause\n", + "\n", + "- support for `\\N{name}` escapes in regular expressions\n", + "\n", + "- dict and dictviews are now iterable in reversed insertion order using `reversed()`\n", + "\n", + "- generalized iterable unpacking in `yield` and `return` statements no longer requires enclosing parentheses\n", + "\n", + "- when the Python interpreter is interrupted by Ctrl-C (`SIGINT`) and the resulting `KeyboardInterrupt` exception is not caught, the Python process now exits via a `SIGINT` signal or with the correct exit code such that the calling process can detect that it died due to a Ctrl-C. Shells on POSIX and Windows use this to properly terminate scripts in interactive sessions\n", + "\n", + "- dict comprehensions have been synced-up with dict literals so that the key is computed first and the value second\n", + "\n", + "- `csv.DictReader` now returns instances of dict instead of a `collections.OrderedDict`. The tool is now faster and uses less memory while still preserving the field order.\n", + "\n", + "- added new alternate constructors `datetime.date.fromisocalendar()` and `datetime.datetime.fromisocalendar()`, which construct date and datetime objects respectively from ISO year, week number, and weekday; these are the inverse of each class’s isocalendar method\n", + "\n", + "- `functools.lru_cache()` can now be used as a straight decorator rather than as a function returning a decorator\n", + "\n", + "- new `functools.cached_property()` decorator, for computed properties cached for the life of the instance\n", + "\n", + "- new combinatoric functions `math.perm()` and `math.comb()`\n", + "\n", + "- many Windows fixes for `os`, `os.path` and `shutil`\n", + "\n", + "- added `post_handshake_auth` to enable and `verify_client_post_handshake()` to initiate TLS 1.3 post-handshake authentication in `ssl`\n", + "\n", + "- added `fmean`, `geometric_mean`, `multimode`, `quantiles` and `NormalDist` into the `statistics` module" + ] + }, + { + "cell_type": "code", + "execution_count": 228, + "id": "a21fdf0a-92d2-4987-93c4-ea68f34f71b3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2019\n", + "('GREHAM', 'John', 'TerryG', 'Eric', 'TerryJ', 'Michael')\n", + "9.333333333333334\n", + "Permutations of 10 things taken 3 at a time: math.perm(10, 3)=720\n", + "Combinations of 10 things taken 3 at a time: math.comb(10, 3)=120\n" + ] + } + ], + "source": [ + "# support for \\N{name} escapes in regular expressions\n", + "import re\n", + "\n", + "notice = \"Copyright © 2019\"\n", + "copyright_year_pattern = re.compile(r\"\\N{copyright sign}\\s*(\\d{4})\")\n", + "print(copyright_year_pattern.search(notice).group(1))\n", + "\n", + "\n", + "# generalized iterable unpacking in yield and return statements no longer requires enclosing parentheses\n", + "def parse(the_pythons):\n", + " first_member, *othermembers = the_pythons.split()\n", + " return first_member.upper(), *othermembers\n", + "\n", + "print(parse(\"Greham John TerryG Eric TerryJ Michael\"))\n", + "\n", + "\n", + "# functools.lru_cache() can now be used as a straight decorator rather than as a function returning a decorator\n", + "import functools\n", + "\n", + "@functools.lru_cache\n", + "def f(x):\n", + " pass\n", + "\n", + "@functools.lru_cache(maxsize=256)\n", + "def f(x):\n", + " pass\n", + "\n", + "\n", + "# new functools.cached_property() decorator, for computed properties cached for the life of the instance\n", + "import statistics\n", + "\n", + "class Dataset:\n", + " def __init__(self, sequence_of_numbers):\n", + " self.data = sequence_of_numbers\n", + "\n", + " @functools.cached_property\n", + " def variance(self):\n", + " return statistics.variance(self.data)\n", + "\n", + "dataset = Dataset((8, 2, 4))\n", + "print(dataset.variance)\n", + "\n", + "\n", + "# new combinatoric functions math.perm() and math.comb()\n", + "import math\n", + "\n", + "print(f\"Permutations of 10 things taken 3 at a time: {math.perm(10, 3)=}\")\n", + "print(f\"Combinations of 10 things taken 3 at a time: {math.comb(10, 3)=}\")" + ] + }, + { + "cell_type": "markdown", + "id": "52f3a2f9-1270-48fe-a5c3-881574ec0191", + "metadata": {}, + "source": [ + "# Python 3.9\n", + "\n", + " Released on October 5th, 2020.\n", + " \n", + " \n", + " ## Highlights\n", + " \n", + " - **PEP 584** – Add Union Operators To dict\n", + " \n", + " - **PEP 585** – Type Hinting Generics In Standard Collections - you can now use built-in collection types such as `list` and `dict` as generic types instead of importing the corresponding capitalized types (e.g. `List` or `Dict`) from `typing`\n", + " \n", + " - **PEP 614** – Relaxing Grammar Restrictions On Decorators\n", + " \n", + " - **PEP 616** – String methods to remove prefixes and suffixes\n", + " \n", + " - **PEP 593** – Flexible function and variable annotations\n", + " \n", + " - **PEP 615** – Support for the IANA Time Zone Database in the Standard Library - the new `zoneinfo` module\n", + " \n", + " - Python now gets the absolute path of the script filename specified on the command line (ex: python3 script.py): the `__file__` attribute of the `__main__` module became an absolute path, rather than a relative path. These paths now remain valid after the current directory is changed by `os.chdir()`. As a side effect, the traceback also displays the absolute path for `__main__` module frames in this case." + ] + }, + { + "cell_type": "code", + "execution_count": 229, + "id": "1f567f26-3783-4435-bcff-48826ea50404", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'key1': 'value1 from x', 'key2': 'value2 from y', 'key3': 'value3 from y'}\n", + "{'key1': 'value1 from x', 'key2': 'value2 from y', 'key3': 'value3 from y'}\n", + "Bravely bold Sir Robin rode forth fro\n" + ] + } + ], + "source": [ + "# PEP 584 – Add Union Operators To dict\n", + "\n", + "# Merge (|) and update (|=) operators have been added to the built-in dict class.\n", + "# Those complement the existing dict.update and {**d1, **d2} methods of merging dictionaries.\n", + "x = {\"key1\": \"value1 from x\", \"key2\": \"value2 from x\"}\n", + "y = {\"key2\": \"value2 from y\", \"key3\": \"value3 from y\"}\n", + "\n", + "print(f\"{x | y}\")\n", + "\n", + "x |= y\n", + "\n", + "print(f\"{x}\")\n", + "\n", + "\n", + "# PEP 616 – String methods to remove prefixes and suffixes\n", + "\n", + "print(\"Bravely bold Sir Robin rode forth from Camelot\".removesuffix(\"m Camelot\"))\n" + ] + }, + { + "cell_type": "markdown", + "id": "910a309a-65ba-48f2-a9c9-9ff5f4de5a3c", + "metadata": {}, + "source": [ + "## Other changes\n", + "\n", + "- The hashlib module can now use *SHA3* hashes and *SHAKE XOF* from *OpenSSL* when available\n", + "\n", + "- new `math.lcm(*integers)` function while `math.gcd(*integers)` now handles multiple arguments. `fractions.gcd()` is removed\n", + "\n", + "- `os.unsetenv()` and `os.putenv()` are now available on Windows\n", + "\n", + "- the Unicode database has been updated to version 13.0.0.\n", + "\n", + "\n", + "## Just for fun...\n", + "\n", + "Notable security feature in 3.9.14\n", + "\n", + "Converting between `int` and `str` in bases other than 2 (binary), 4, 8 (octal), 16 (hexadecimal), or 32 such as base 10 (decimal) now raises a `ValueError` if the number of digits in string form is above a limit to avoid potential denial of service attacks due to the algorithmic complexity. This is a mitigation for *CVE-2020-10735*.\n", + "This limit can be configured or disabled by environment variable, command line flag, or sys APIs.\n", + "See the integer string conversion length limitation documentation. The default limit is 4300 digits in string form.\n" + ] + }, + { + "cell_type": "markdown", + "id": "bac26435-89c5-4b89-af37-340fd9a9556c", + "metadata": {}, + "source": [ + "# Python 3.10\n", + "\n", + " Released on October 4th, 2021.\n", + " \n", + " \n", + " ## Highlights\n", + " \n", + " - Parenthesized context managers are now officially allowed\n", + " \n", + " - Better error messages\n", + " \n", + " - **PEP 634**, **PEP 635**, **PEP 636** - Structural pattern matching\n", + " \n", + " - **PEP 626** - Precise line numbers for debugging and other tools\n", + " \n", + " - **PEP 604**, **PEP 612**, **PEP 613** - Various typing features\n", + " \n", + " - **PEP 644** - Require OpenSSL 1.1.1 or newer\n", + " \n", + " - **PEP 632** - Deprecate distutils module" + ] + }, + { + "cell_type": "code", + "execution_count": 230, + "id": "11aaff48-28a3-49f5-86b6-059af6ab534d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Started with: ['the', 'clock']\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 230, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Parenthesized context managers are now officially allowed\n", + "import io\n", + "\n", + "with (\n", + " io.open(\"input_file.dat\", \"rb\") as input_fp,\n", + " io.open(\"output_file.dat\", \"wb\") as output_fp,\n", + "):\n", + " data = input_fp.read()\n", + " # do some processing magic on data\n", + " output_fp.write(data)\n", + "\n", + "\n", + "# Better error messages:\n", + "\n", + "# the_pythons = [\"Greham\", \"John\", \"Terry G\", \"Eric\",\n", + "# \"Terry J\", \"Michael\"\n", + "# some_other_code = foo()\n", + "\n", + "# Results in:\n", + "\n", + "# Python >= 3.10\n", + "# Cell In [25], line 15\n", + "# the_pythons = [\"Greham\", \"John\", \"Terry G\", \"Eric\",\n", + "# ^\n", + "# SyntaxError: '[' was never closed\n", + "\n", + "# Python < 3.10\n", + "# File \"test.py\", line 16\n", + "# some_other_code = foo()\n", + "# ^\n", + "# SyntaxError: invalid syntax\n", + "\n", + "\n", + "# PEP 634, PEP 635, PEP 636 - Structural pattern matching\n", + "command = \"start the clock\"\n", + "# command = input(\"Command: \")\n", + "match command.split():\n", + " case [\"start\", *args]:\n", + " print(f\"Started with: {args}\")\n", + " case [\"stop\"] | [\"quit\"]:\n", + " print(\"Stopped\")\n", + " case [\"go\", (\"east\" | \"north\" | \"south\" | \"west\") as direction]: # capturing matched sub-pattern\n", + " print(f\"Going {direction!r}\")\n", + " case [\"move\", direction] if direction in (\"east\", \"north\", \"south\", \"west\"): # guard / pattern condition - only checked if the pattern matches\n", + " print(f\"Moving {direction!r}\")\n", + " case [unknown, *args]:\n", + " print(f\"Unknown command {unknown!r} used with: {args}\")\n", + " case _:\n", + " print(\"Something completely unexpected happened :)\")\n", + "\n", + "\n", + "# PEP 604, PEP 612, PEP 613 - Various typing features\n", + "import typing\n", + "\n", + "def square(number: typing.Union[int, float]) -> typing.Union[int, float]:\n", + " return number ** 2\n", + "\n", + "# can now be written as...\n", + "def square(number: int | float) -> int | float:\n", + " return number ** 2\n", + "\n", + "isinstance(1, int | str)" + ] + }, + { + "cell_type": "markdown", + "id": "0d6829ee-dfaa-4841-a1c4-b8632d9f30f6", + "metadata": {}, + "source": [ + "## Other changes\n", + "\n", + "- the `zip()` function now has an optional *strict* flag, used to require that all the iterables have an equal length\n", + "\n", + "- the entire `distutils` package is deprecated, to be removed in Python 3.12. Its functionality for specifying package builds has already been completely replaced by third-party packages `setuptools` and `packaging`\n", + "\n", + "- new `itertools.pairwise()`\n", + "\n", + "- `os.path.realpath()` now accepts a strict keyword-only argument. When set to `True`, `OSError` is raised if a path doesn’t exist or a symlink loop is encountered\n", + "\n", + "- added slice support to `PurePath.parents`\n", + "\n", + "- added the `statistics.covariance()`, Pearson’s `statistics.correlation()`, and simple `statistics.linear_regression()` functions\n", + "\n", + "- many changes in the `ssl` module" + ] + }, + { + "cell_type": "markdown", + "id": "ec96310b-2b8d-45f3-9cac-6ec33861483b", + "metadata": {}, + "source": [ + "# Python 3.11\n", + "\n", + "Released on October 24th, 2022.\n", + "\n", + "\n", + "## Highlights\n", + "\n", + "- The first reference implementation (CPython) using C11 instead of C89\n", + "\n", + "- Python 3.11 is between 10-60% faster than Python 3.10. On average, we measured a 1.25x speedup on the standard benchmark suite\n", + "\n", + "- **PEP 654** - Exception groups and except* - enable a program to raise and handle multiple unrelated exceptions simultaneously\n", + "\n", + "- **PEP 678** - Exceptions can be enriched with notes\n", + "\n", + "- **PEP 680** - new module *tomllib* - Support for parsing *TOML* in the Standard Library\n", + "\n", + "- **PEP 657** - Fine-grained error locations in tracebacks\n", + "\n", + "- **PEP 655**, **PEP 673**, **PEP 675** - Various `typing` features (LiteralString, Self, Required, NotRequired) and other\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 231, + "id": "ef9285ea-2bdb-4fb0-968d-833011fe0724", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "KeyError detected\n", + "TypeError detected\n", + "KeyError detected\n", + "TypeError detected\n", + "bad type - ['Really bad types at work']\n" + ] + } + ], + "source": [ + "# PEP 654 - Exception groups and except* - enable a program to raise and handle multiple unrelated exceptions simultaneously\n", + "\n", + "# new builtin exception types: BaseExceptionGroup(BaseException) and ExceptionGroup(BaseExceptionGroup, Exception).\n", + "# They are assignable to Exception.__cause__ and Exception.__context__,\n", + "# and they can be raised and handled as any exception with\n", + "# raise ExceptionGroup(...) and try: ... except ExceptionGroup: ... or\n", + "# raise BaseExceptionGroup(...) and try: ... except BaseExceptionGroup: ....\n", + "\n", + "my_dict = {\"test1\": \"foo\", \"test2\": \"bar\"}\n", + "\n", + "for key in (\"test3\", [1, 8]):\n", + " try:\n", + " result = my_dict[key]\n", + " except KeyError:\n", + " print(\"KeyError detected\")\n", + " except TypeError:\n", + " print(\"TypeError detected\")\n", + "\n", + "for key in (\"test3\", [1, 8]):\n", + " try:\n", + " result = my_dict[key]\n", + " except* (KeyError, TypeError) as eg:\n", + " for e in eg.exceptions:\n", + " print(f\"{type(e).__name__} detected\")\n", + " \n", + "\n", + "# PEP 678 – Enriching exceptions with notes\n", + "# BaseException gains a new method .add_note(note: str).\n", + "# If note is a string, .add_note(note) appends it to the __notes__ list, creating the attribute if it does not already exist.\n", + "# If note is not a string, .add_note() raises TypeError.\n", + "\n", + "try:\n", + " try:\n", + " raise TypeError(\"bad type\")\n", + " except Exception as e:\n", + " e.add_note(\"Really bad types at work\")\n", + " raise\n", + "except Exception as e:\n", + " print(f\"{e!s} - {e.__notes__}\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "a3e0bcdd-69b8-4cb3-92e1-eeeb250b38ae", + "metadata": {}, + "source": [ + "## Other changes\n", + "\n", + "- starred unpacking expressions can now be used in `for` statements\n", + "\n", + "- added a -P command line option and a *PYTHONSAFEPATH* environment variable, which disable the automatic prepending to `sys.path` of the script’s directory when running a script, or the current directory when using -c and -m. This ensures only stdlib and installed modules are picked up by import, and avoids unintentionally or maliciously shadowing modules with those in a local (and typically user-writable) directory\n", + "\n", + "- **PEP 682** – Format specifier for signed zero\n", + "\n", + "- *siphash13* is added as a new internal hashing algorithm. It has similar security properties as *siphash24*, but it is slightly faster for long inputs (CPython specific)\n", + "\n", + "- added non parallel-safe `contextlib.chdir()` context manager to change the current working directory and then restore it on exit. Simple wrapper around `chdir()`\n", + "\n", + "- added `datetime.UTC`, a convenience alias for `datetime.timezone.utc`" + ] + }, + { + "cell_type": "code", + "execution_count": 232, + "id": "f1f9977c-20f4-4bc1-9fa7-14acd0f16193", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n", + "3\n", + "4\n", + "5\n", + "0.0\n", + "+0.0\n" + ] + } + ], + "source": [ + "# starred unpacking expressions can now be used in `for` statements\n", + "t1 = (1, 2, 3)\n", + "t2 = (3, 4, 5)\n", + "\n", + "for i in *t1, *t2:\n", + " print(i)\n", + "\n", + "\n", + "# PEP 682 – Format specifier for signed zero\n", + "# When z is present, negative zero (whether the original value or the result of rounding) will be normalized to positive zero\n", + "import decimal\n", + "\n", + "x = -.00001\n", + "print(f\"{x:z.1f}\")\n", + "\n", + "x = decimal.Decimal('-.00001')\n", + "print(f\"{x:+z.1f}\")\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "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.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/python/python_3_8to_3_11.ipynb b/notebooks/python/python_3_8to_3_11.ipynb deleted file mode 100644 index 733f7dd..0000000 --- a/notebooks/python/python_3_8to_3_11.ipynb +++ /dev/null @@ -1,64 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "b3f102cb-0f33-43ad-a808-e8f3c171b370", - "metadata": {}, - "source": [ - "# Python 3.8\n", - "\n", - "Released on October 14th, 2019." - ] - }, - { - "cell_type": "markdown", - "id": "52f3a2f9-1270-48fe-a5c3-881574ec0191", - "metadata": {}, - "source": [ - "# Python 3.9\n", - "\n", - " Released on October 5th, 2020." - ] - }, - { - "cell_type": "markdown", - "id": "bac26435-89c5-4b89-af37-340fd9a9556c", - "metadata": {}, - "source": [ - "# Python 3.10\n", - "\n", - " Released on October 4, 2021." - ] - }, - { - "cell_type": "markdown", - "id": "ec96310b-2b8d-45f3-9cac-6ec33861483b", - "metadata": {}, - "source": [ - "# Python 3.11\n", - "\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "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.8.10" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/notebooks/python/python_oo.ipynb b/notebooks/python/python_oo.ipynb index df5907b..9f0774a 100644 --- a/notebooks/python/python_oo.ipynb +++ b/notebooks/python/python_oo.ipynb @@ -1216,6 +1216,8 @@ "\n", " - `__hash__`\n", " \n", + " - `__match_args__`\n", + "\n", " - ...\n", "\n", "- [Raymond Hettinger - Super considered super! - PyCon 2015](https://www.youtube.com/watch?v=EiOglTERPEo)\n", @@ -1240,7 +1242,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.10" + "version": "3.11.0" } }, "nbformat": 4, -- cgit v1.3