diff options
Diffstat (limited to 'notebooks')
| -rw-r--r-- | notebooks/python/input_file.dat | 0 | ||||
| -rw-r--r-- | notebooks/python/python_3_8_to_3_11.ipynb | 619 | ||||
| -rw-r--r-- | notebooks/python/python_3_8to_3_11.ipynb | 64 | ||||
| -rw-r--r-- | notebooks/python/python_oo.ipynb | 4 |
4 files changed, 622 insertions, 65 deletions
diff --git a/notebooks/python/input_file.dat b/notebooks/python/input_file.dat new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/notebooks/python/input_file.dat | |||
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 @@ | |||
| 1 | { | ||
| 2 | "cells": [ | ||
| 3 | { | ||
| 4 | "cell_type": "markdown", | ||
| 5 | "id": "95c6942c-cd6a-437f-a35e-f6bbaf3555bd", | ||
| 6 | "metadata": {}, | ||
| 7 | "source": [ | ||
| 8 | "# A very brief summary of changes introduced in Python 3.8, 3.9, 3.10 and 3.11\n" | ||
| 9 | ] | ||
| 10 | }, | ||
| 11 | { | ||
| 12 | "cell_type": "markdown", | ||
| 13 | "id": "b3f102cb-0f33-43ad-a808-e8f3c171b370", | ||
| 14 | "metadata": {}, | ||
| 15 | "source": [ | ||
| 16 | "# Python 3.8\n", | ||
| 17 | "\n", | ||
| 18 | "Released on October 14th, 2019.\n", | ||
| 19 | "\n", | ||
| 20 | "\n", | ||
| 21 | "## Highlights\n", | ||
| 22 | "\n", | ||
| 23 | "- **PEP 572** – Assignment Expressions - The \"walrus operator\"\n", | ||
| 24 | "\n", | ||
| 25 | "- **PEP 570** – Python Positional-Only Parameters\n", | ||
| 26 | "\n", | ||
| 27 | "- **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", | ||
| 28 | "\n", | ||
| 29 | "- f-strings support = for self-documenting expressions and debugging" | ||
| 30 | ] | ||
| 31 | }, | ||
| 32 | { | ||
| 33 | "cell_type": "code", | ||
| 34 | "execution_count": 226, | ||
| 35 | "id": "a21e461a-8a7c-49d2-8a53-ab63ff2488bb", | ||
| 36 | "metadata": {}, | ||
| 37 | "outputs": [ | ||
| 38 | { | ||
| 39 | "name": "stdout", | ||
| 40 | "output_type": "stream", | ||
| 41 | "text": [ | ||
| 42 | "List is too long (6 elements, expected <= 10)\n", | ||
| 43 | "List is too long (6 elements, expected <= 10)\n", | ||
| 44 | "my_list[3]='Eric'\n", | ||
| 45 | "my_list[4]='Terry J'\n", | ||
| 46 | "my_list[5]=Michael\n" | ||
| 47 | ] | ||
| 48 | } | ||
| 49 | ], | ||
| 50 | "source": [ | ||
| 51 | "# The walrus operator:\n", | ||
| 52 | "\n", | ||
| 53 | "my_list = [\"Greham\", \"John\", \"Terry G\", \"Eric\", \"Terry J\", \"Michael\"]\n", | ||
| 54 | "\n", | ||
| 55 | "# Python < 3.8\n", | ||
| 56 | "list_length = len(my_list)\n", | ||
| 57 | "if list_length > 5:\n", | ||
| 58 | " print(f\"List is too long ({list_length} elements, expected <= 10)\")\n", | ||
| 59 | "\n", | ||
| 60 | "# while using the walrus operator...\n", | ||
| 61 | "if (list_length := len(my_list)) > 5:\n", | ||
| 62 | " print(f\"List is too long ({list_length} elements, expected <= 10)\")\n", | ||
| 63 | "\n", | ||
| 64 | "\n", | ||
| 65 | "# f-strings support for self-documenting expressions and debugging using =\n", | ||
| 66 | "print(f\"{my_list[3]=!r}\")\n", | ||
| 67 | "print(f\"{my_list[4]=}\") # !r is implicit\n", | ||
| 68 | "print(f\"{my_list[5]=!s}\")" | ||
| 69 | ] | ||
| 70 | }, | ||
| 71 | { | ||
| 72 | "cell_type": "code", | ||
| 73 | "execution_count": 227, | ||
| 74 | "id": "99b75989-e991-4f77-a62e-01776f5b606c", | ||
| 75 | "metadata": {}, | ||
| 76 | "outputs": [ | ||
| 77 | { | ||
| 78 | "name": "stdout", | ||
| 79 | "output_type": "stream", | ||
| 80 | "text": [ | ||
| 81 | "10 20 {'a': 1, 'b': 2, 'c': 3}\n" | ||
| 82 | ] | ||
| 83 | } | ||
| 84 | ], | ||
| 85 | "source": [ | ||
| 86 | "# Positional only parameters:\n", | ||
| 87 | "# def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):\n", | ||
| 88 | "# ----------- ---------- ----------\n", | ||
| 89 | "# | | |\n", | ||
| 90 | "# | Positional or keyword |\n", | ||
| 91 | "# | - Keyword only\n", | ||
| 92 | "# -- Positional only\n", | ||
| 93 | "\n", | ||
| 94 | "# Positional-only parameters give more control to library authors to better\n", | ||
| 95 | "# express the intended usage of an API and allows the API to evolve in a safe, backward-compatible way.\n", | ||
| 96 | "# Additionally, it makes the Python language more consistent with existing documentation and\n", | ||
| 97 | "# the behavior of various “builtin” and standard library functions.\n", | ||
| 98 | "\n", | ||
| 99 | "# One use case for this notation is that it allows pure Python functions to fully emulate behaviors of existing C coded functions.\n", | ||
| 100 | "# For example, the built-in divmod() function does not accept keyword arguments:\n", | ||
| 101 | "def divmod(a, b, /):\n", | ||
| 102 | " \"\"\"Emulate the built in divmod() function\"\"\"\n", | ||
| 103 | " return (a // b, a % b)\n", | ||
| 104 | "\n", | ||
| 105 | "# Another use case is to preclude keyword arguments when the parameter name is not helpful.\n", | ||
| 106 | "# For example, the builtin len() function has the signature len(obj, /).\n", | ||
| 107 | "# This precludes awkward calls such as: len(obj=\"hello\"), where the \"obj\" keyword argument impairs readability.\n", | ||
| 108 | "\n", | ||
| 109 | "# 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", | ||
| 110 | "\n", | ||
| 111 | "def my_func(a, b, /, **kwargs):\n", | ||
| 112 | " print(a, b, kwargs)\n", | ||
| 113 | "my_func(10, 20, a=1, b=2, c=3)" | ||
| 114 | ] | ||
| 115 | }, | ||
| 116 | { | ||
| 117 | "cell_type": "markdown", | ||
| 118 | "id": "1801f5cb-6620-43c9-a1c8-1ada25b046bf", | ||
| 119 | "metadata": {}, | ||
| 120 | "source": [ | ||
| 121 | "## Other changes\n", | ||
| 122 | "\n", | ||
| 123 | "- `continue` can be used in the `finally` clause\n", | ||
| 124 | "\n", | ||
| 125 | "- support for `\\N{name}` escapes in regular expressions\n", | ||
| 126 | "\n", | ||
| 127 | "- dict and dictviews are now iterable in reversed insertion order using `reversed()`\n", | ||
| 128 | "\n", | ||
| 129 | "- generalized iterable unpacking in `yield` and `return` statements no longer requires enclosing parentheses\n", | ||
| 130 | "\n", | ||
| 131 | "- 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", | ||
| 132 | "\n", | ||
| 133 | "- dict comprehensions have been synced-up with dict literals so that the key is computed first and the value second\n", | ||
| 134 | "\n", | ||
| 135 | "- `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", | ||
| 136 | "\n", | ||
| 137 | "- 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", | ||
| 138 | "\n", | ||
| 139 | "- `functools.lru_cache()` can now be used as a straight decorator rather than as a function returning a decorator\n", | ||
| 140 | "\n", | ||
| 141 | "- new `functools.cached_property()` decorator, for computed properties cached for the life of the instance\n", | ||
| 142 | "\n", | ||
| 143 | "- new combinatoric functions `math.perm()` and `math.comb()`\n", | ||
| 144 | "\n", | ||
| 145 | "- many Windows fixes for `os`, `os.path` and `shutil`\n", | ||
| 146 | "\n", | ||
| 147 | "- added `post_handshake_auth` to enable and `verify_client_post_handshake()` to initiate TLS 1.3 post-handshake authentication in `ssl`\n", | ||
| 148 | "\n", | ||
| 149 | "- added `fmean`, `geometric_mean`, `multimode`, `quantiles` and `NormalDist` into the `statistics` module" | ||
| 150 | ] | ||
| 151 | }, | ||
| 152 | { | ||
| 153 | "cell_type": "code", | ||
| 154 | "execution_count": 228, | ||
| 155 | "id": "a21fdf0a-92d2-4987-93c4-ea68f34f71b3", | ||
| 156 | "metadata": {}, | ||
| 157 | "outputs": [ | ||
| 158 | { | ||
| 159 | "name": "stdout", | ||
| 160 | "output_type": "stream", | ||
| 161 | "text": [ | ||
| 162 | "2019\n", | ||
| 163 | "('GREHAM', 'John', 'TerryG', 'Eric', 'TerryJ', 'Michael')\n", | ||
| 164 | "9.333333333333334\n", | ||
| 165 | "Permutations of 10 things taken 3 at a time: math.perm(10, 3)=720\n", | ||
| 166 | "Combinations of 10 things taken 3 at a time: math.comb(10, 3)=120\n" | ||
| 167 | ] | ||
| 168 | } | ||
| 169 | ], | ||
| 170 | "source": [ | ||
| 171 | "# support for \\N{name} escapes in regular expressions\n", | ||
| 172 | "import re\n", | ||
| 173 | "\n", | ||
| 174 | "notice = \"Copyright © 2019\"\n", | ||
| 175 | "copyright_year_pattern = re.compile(r\"\\N{copyright sign}\\s*(\\d{4})\")\n", | ||
| 176 | "print(copyright_year_pattern.search(notice).group(1))\n", | ||
| 177 | "\n", | ||
| 178 | "\n", | ||
| 179 | "# generalized iterable unpacking in yield and return statements no longer requires enclosing parentheses\n", | ||
| 180 | "def parse(the_pythons):\n", | ||
| 181 | " first_member, *othermembers = the_pythons.split()\n", | ||
| 182 | " return first_member.upper(), *othermembers\n", | ||
| 183 | "\n", | ||
| 184 | "print(parse(\"Greham John TerryG Eric TerryJ Michael\"))\n", | ||
| 185 | "\n", | ||
| 186 | "\n", | ||
| 187 | "# functools.lru_cache() can now be used as a straight decorator rather than as a function returning a decorator\n", | ||
| 188 | "import functools\n", | ||
| 189 | "\n", | ||
| 190 | "@functools.lru_cache\n", | ||
| 191 | "def f(x):\n", | ||
| 192 | " pass\n", | ||
| 193 | "\n", | ||
| 194 | "@functools.lru_cache(maxsize=256)\n", | ||
| 195 | "def f(x):\n", | ||
| 196 | " pass\n", | ||
| 197 | "\n", | ||
| 198 | "\n", | ||
| 199 | "# new functools.cached_property() decorator, for computed properties cached for the life of the instance\n", | ||
| 200 | "import statistics\n", | ||
| 201 | "\n", | ||
| 202 | "class Dataset:\n", | ||
| 203 | " def __init__(self, sequence_of_numbers):\n", | ||
| 204 | " self.data = sequence_of_numbers\n", | ||
| 205 | "\n", | ||
| 206 | " @functools.cached_property\n", | ||
| 207 | " def variance(self):\n", | ||
| 208 | " return statistics.variance(self.data)\n", | ||
| 209 | "\n", | ||
| 210 | "dataset = Dataset((8, 2, 4))\n", | ||
| 211 | "print(dataset.variance)\n", | ||
| 212 | "\n", | ||
| 213 | "\n", | ||
| 214 | "# new combinatoric functions math.perm() and math.comb()\n", | ||
| 215 | "import math\n", | ||
| 216 | "\n", | ||
| 217 | "print(f\"Permutations of 10 things taken 3 at a time: {math.perm(10, 3)=}\")\n", | ||
| 218 | "print(f\"Combinations of 10 things taken 3 at a time: {math.comb(10, 3)=}\")" | ||
| 219 | ] | ||
| 220 | }, | ||
| 221 | { | ||
| 222 | "cell_type": "markdown", | ||
| 223 | "id": "52f3a2f9-1270-48fe-a5c3-881574ec0191", | ||
| 224 | "metadata": {}, | ||
| 225 | "source": [ | ||
| 226 | "# Python 3.9\n", | ||
| 227 | "\n", | ||
| 228 | " Released on October 5th, 2020.\n", | ||
| 229 | " \n", | ||
| 230 | " \n", | ||
| 231 | " ## Highlights\n", | ||
| 232 | " \n", | ||
| 233 | " - **PEP 584** – Add Union Operators To dict\n", | ||
| 234 | " \n", | ||
| 235 | " - **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", | ||
| 236 | " \n", | ||
| 237 | " - **PEP 614** – Relaxing Grammar Restrictions On Decorators\n", | ||
| 238 | " \n", | ||
| 239 | " - **PEP 616** – String methods to remove prefixes and suffixes\n", | ||
| 240 | " \n", | ||
| 241 | " - **PEP 593** – Flexible function and variable annotations\n", | ||
| 242 | " \n", | ||
| 243 | " - **PEP 615** – Support for the IANA Time Zone Database in the Standard Library - the new `zoneinfo` module\n", | ||
| 244 | " \n", | ||
| 245 | " - 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." | ||
| 246 | ] | ||
| 247 | }, | ||
| 248 | { | ||
| 249 | "cell_type": "code", | ||
| 250 | "execution_count": 229, | ||
| 251 | "id": "1f567f26-3783-4435-bcff-48826ea50404", | ||
| 252 | "metadata": {}, | ||
| 253 | "outputs": [ | ||
| 254 | { | ||
| 255 | "name": "stdout", | ||
| 256 | "output_type": "stream", | ||
| 257 | "text": [ | ||
| 258 | "{'key1': 'value1 from x', 'key2': 'value2 from y', 'key3': 'value3 from y'}\n", | ||
| 259 | "{'key1': 'value1 from x', 'key2': 'value2 from y', 'key3': 'value3 from y'}\n", | ||
| 260 | "Bravely bold Sir Robin rode forth fro\n" | ||
| 261 | ] | ||
| 262 | } | ||
| 263 | ], | ||
| 264 | "source": [ | ||
| 265 | "# PEP 584 – Add Union Operators To dict\n", | ||
| 266 | "\n", | ||
| 267 | "# Merge (|) and update (|=) operators have been added to the built-in dict class.\n", | ||
| 268 | "# Those complement the existing dict.update and {**d1, **d2} methods of merging dictionaries.\n", | ||
| 269 | "x = {\"key1\": \"value1 from x\", \"key2\": \"value2 from x\"}\n", | ||
| 270 | "y = {\"key2\": \"value2 from y\", \"key3\": \"value3 from y\"}\n", | ||
| 271 | "\n", | ||
| 272 | "print(f\"{x | y}\")\n", | ||
| 273 | "\n", | ||
| 274 | "x |= y\n", | ||
| 275 | "\n", | ||
| 276 | "print(f\"{x}\")\n", | ||
| 277 | "\n", | ||
| 278 | "\n", | ||
| 279 | "# PEP 616 – String methods to remove prefixes and suffixes\n", | ||
| 280 | "\n", | ||
| 281 | "print(\"Bravely bold Sir Robin rode forth from Camelot\".removesuffix(\"m Camelot\"))\n" | ||
| 282 | ] | ||
| 283 | }, | ||
| 284 | { | ||
| 285 | "cell_type": "markdown", | ||
| 286 | "id": "910a309a-65ba-48f2-a9c9-9ff5f4de5a3c", | ||
| 287 | "metadata": {}, | ||
| 288 | "source": [ | ||
| 289 | "## Other changes\n", | ||
| 290 | "\n", | ||
| 291 | "- The hashlib module can now use *SHA3* hashes and *SHAKE XOF* from *OpenSSL* when available\n", | ||
| 292 | "\n", | ||
| 293 | "- new `math.lcm(*integers)` function while `math.gcd(*integers)` now handles multiple arguments. `fractions.gcd()` is removed\n", | ||
| 294 | "\n", | ||
| 295 | "- `os.unsetenv()` and `os.putenv()` are now available on Windows\n", | ||
| 296 | "\n", | ||
| 297 | "- the Unicode database has been updated to version 13.0.0.\n", | ||
| 298 | "\n", | ||
| 299 | "\n", | ||
| 300 | "## Just for fun...\n", | ||
| 301 | "\n", | ||
| 302 | "Notable security feature in 3.9.14\n", | ||
| 303 | "\n", | ||
| 304 | "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", | ||
| 305 | "This limit can be configured or disabled by environment variable, command line flag, or sys APIs.\n", | ||
| 306 | "See the integer string conversion length limitation documentation. The default limit is 4300 digits in string form.\n" | ||
| 307 | ] | ||
| 308 | }, | ||
| 309 | { | ||
| 310 | "cell_type": "markdown", | ||
| 311 | "id": "bac26435-89c5-4b89-af37-340fd9a9556c", | ||
| 312 | "metadata": {}, | ||
| 313 | "source": [ | ||
| 314 | "# Python 3.10\n", | ||
| 315 | "\n", | ||
| 316 | " Released on October 4th, 2021.\n", | ||
| 317 | " \n", | ||
| 318 | " \n", | ||
| 319 | " ## Highlights\n", | ||
| 320 | " \n", | ||
| 321 | " - Parenthesized context managers are now officially allowed\n", | ||
| 322 | " \n", | ||
| 323 | " - Better error messages\n", | ||
| 324 | " \n", | ||
| 325 | " - **PEP 634**, **PEP 635**, **PEP 636** - Structural pattern matching\n", | ||
| 326 | " \n", | ||
| 327 | " - **PEP 626** - Precise line numbers for debugging and other tools\n", | ||
| 328 | " \n", | ||
| 329 | " - **PEP 604**, **PEP 612**, **PEP 613** - Various typing features\n", | ||
| 330 | " \n", | ||
| 331 | " - **PEP 644** - Require OpenSSL 1.1.1 or newer\n", | ||
| 332 | " \n", | ||
| 333 | " - **PEP 632** - Deprecate distutils module" | ||
| 334 | ] | ||
| 335 | }, | ||
| 336 | { | ||
| 337 | "cell_type": "code", | ||
| 338 | "execution_count": 230, | ||
| 339 | "id": "11aaff48-28a3-49f5-86b6-059af6ab534d", | ||
| 340 | "metadata": {}, | ||
| 341 | "outputs": [ | ||
| 342 | { | ||
| 343 | "name": "stdout", | ||
| 344 | "output_type": "stream", | ||
| 345 | "text": [ | ||
| 346 | "Started with: ['the', 'clock']\n" | ||
| 347 | ] | ||
| 348 | }, | ||
| 349 | { | ||
| 350 | "data": { | ||
| 351 | "text/plain": [ | ||
| 352 | "True" | ||
| 353 | ] | ||
| 354 | }, | ||
| 355 | "execution_count": 230, | ||
| 356 | "metadata": {}, | ||
| 357 | "output_type": "execute_result" | ||
| 358 | } | ||
| 359 | ], | ||
| 360 | "source": [ | ||
| 361 | "# Parenthesized context managers are now officially allowed\n", | ||
| 362 | "import io\n", | ||
| 363 | "\n", | ||
| 364 | "with (\n", | ||
| 365 | " io.open(\"input_file.dat\", \"rb\") as input_fp,\n", | ||
| 366 | " io.open(\"output_file.dat\", \"wb\") as output_fp,\n", | ||
| 367 | "):\n", | ||
| 368 | " data = input_fp.read()\n", | ||
| 369 | " # do some processing magic on data\n", | ||
| 370 | " output_fp.write(data)\n", | ||
| 371 | "\n", | ||
| 372 | "\n", | ||
| 373 | "# Better error messages:\n", | ||
| 374 | "\n", | ||
| 375 | "# the_pythons = [\"Greham\", \"John\", \"Terry G\", \"Eric\",\n", | ||
| 376 | "# \"Terry J\", \"Michael\"\n", | ||
| 377 | "# some_other_code = foo()\n", | ||
| 378 | "\n", | ||
| 379 | "# Results in:\n", | ||
| 380 | "\n", | ||
| 381 | "# Python >= 3.10\n", | ||
| 382 | "# Cell In [25], line 15\n", | ||
| 383 | "# the_pythons = [\"Greham\", \"John\", \"Terry G\", \"Eric\",\n", | ||
| 384 | "# ^\n", | ||
| 385 | "# SyntaxError: '[' was never closed\n", | ||
| 386 | "\n", | ||
| 387 | "# Python < 3.10\n", | ||
| 388 | "# File \"test.py\", line 16\n", | ||
| 389 | "# some_other_code = foo()\n", | ||
| 390 | "# ^\n", | ||
| 391 | "# SyntaxError: invalid syntax\n", | ||
| 392 | "\n", | ||
| 393 | "\n", | ||
| 394 | "# PEP 634, PEP 635, PEP 636 - Structural pattern matching\n", | ||
| 395 | "command = \"start the clock\"\n", | ||
| 396 | "# command = input(\"Command: \")\n", | ||
| 397 | "match command.split():\n", | ||
| 398 | " case [\"start\", *args]:\n", | ||
| 399 | " print(f\"Started with: {args}\")\n", | ||
| 400 | " case [\"stop\"] | [\"quit\"]:\n", | ||
| 401 | " print(\"Stopped\")\n", | ||
| 402 | " case [\"go\", (\"east\" | \"north\" | \"south\" | \"west\") as direction]: # capturing matched sub-pattern\n", | ||
| 403 | " print(f\"Going {direction!r}\")\n", | ||
| 404 | " case [\"move\", direction] if direction in (\"east\", \"north\", \"south\", \"west\"): # guard / pattern condition - only checked if the pattern matches\n", | ||
| 405 | " print(f\"Moving {direction!r}\")\n", | ||
| 406 | " case [unknown, *args]:\n", | ||
| 407 | " print(f\"Unknown command {unknown!r} used with: {args}\")\n", | ||
| 408 | " case _:\n", | ||
| 409 | " print(\"Something completely unexpected happened :)\")\n", | ||
| 410 | "\n", | ||
| 411 | "\n", | ||
| 412 | "# PEP 604, PEP 612, PEP 613 - Various typing features\n", | ||
| 413 | "import typing\n", | ||
| 414 | "\n", | ||
| 415 | "def square(number: typing.Union[int, float]) -> typing.Union[int, float]:\n", | ||
| 416 | " return number ** 2\n", | ||
| 417 | "\n", | ||
| 418 | "# can now be written as...\n", | ||
| 419 | "def square(number: int | float) -> int | float:\n", | ||
| 420 | " return number ** 2\n", | ||
| 421 | "\n", | ||
| 422 | "isinstance(1, int | str)" | ||
| 423 | ] | ||
| 424 | }, | ||
| 425 | { | ||
| 426 | "cell_type": "markdown", | ||
| 427 | "id": "0d6829ee-dfaa-4841-a1c4-b8632d9f30f6", | ||
| 428 | "metadata": {}, | ||
| 429 | "source": [ | ||
| 430 | "## Other changes\n", | ||
| 431 | "\n", | ||
| 432 | "- the `zip()` function now has an optional *strict* flag, used to require that all the iterables have an equal length\n", | ||
| 433 | "\n", | ||
| 434 | "- 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", | ||
| 435 | "\n", | ||
| 436 | "- new `itertools.pairwise()`\n", | ||
| 437 | "\n", | ||
| 438 | "- `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", | ||
| 439 | "\n", | ||
| 440 | "- added slice support to `PurePath.parents`\n", | ||
| 441 | "\n", | ||
| 442 | "- added the `statistics.covariance()`, Pearson’s `statistics.correlation()`, and simple `statistics.linear_regression()` functions\n", | ||
| 443 | "\n", | ||
| 444 | "- many changes in the `ssl` module" | ||
| 445 | ] | ||
| 446 | }, | ||
| 447 | { | ||
| 448 | "cell_type": "markdown", | ||
| 449 | "id": "ec96310b-2b8d-45f3-9cac-6ec33861483b", | ||
| 450 | "metadata": {}, | ||
| 451 | "source": [ | ||
| 452 | "# Python 3.11\n", | ||
| 453 | "\n", | ||
| 454 | "Released on October 24th, 2022.\n", | ||
| 455 | "\n", | ||
| 456 | "\n", | ||
| 457 | "## Highlights\n", | ||
| 458 | "\n", | ||
| 459 | "- The first reference implementation (CPython) using C11 instead of C89\n", | ||
| 460 | "\n", | ||
| 461 | "- 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", | ||
| 462 | "\n", | ||
| 463 | "- **PEP 654** - Exception groups and except* - enable a program to raise and handle multiple unrelated exceptions simultaneously\n", | ||
| 464 | "\n", | ||
| 465 | "- **PEP 678** - Exceptions can be enriched with notes\n", | ||
| 466 | "\n", | ||
| 467 | "- **PEP 680** - new module *tomllib* - Support for parsing *TOML* in the Standard Library\n", | ||
| 468 | "\n", | ||
| 469 | "- **PEP 657** - Fine-grained error locations in tracebacks\n", | ||
| 470 | "\n", | ||
| 471 | "- **PEP 655**, **PEP 673**, **PEP 675** - Various `typing` features (LiteralString, Self, Required, NotRequired) and other\n", | ||
| 472 | "\n", | ||
| 473 | "\n" | ||
| 474 | ] | ||
| 475 | }, | ||
| 476 | { | ||
| 477 | "cell_type": "code", | ||
| 478 | "execution_count": 231, | ||
| 479 | "id": "ef9285ea-2bdb-4fb0-968d-833011fe0724", | ||
| 480 | "metadata": {}, | ||
| 481 | "outputs": [ | ||
| 482 | { | ||
| 483 | "name": "stdout", | ||
| 484 | "output_type": "stream", | ||
| 485 | "text": [ | ||
| 486 | "KeyError detected\n", | ||
| 487 | "TypeError detected\n", | ||
| 488 | "KeyError detected\n", | ||
| 489 | "TypeError detected\n", | ||
| 490 | "bad type - ['Really bad types at work']\n" | ||
| 491 | ] | ||
| 492 | } | ||
| 493 | ], | ||
| 494 | "source": [ | ||
| 495 | "# PEP 654 - Exception groups and except* - enable a program to raise and handle multiple unrelated exceptions simultaneously\n", | ||
| 496 | "\n", | ||
| 497 | "# new builtin exception types: BaseExceptionGroup(BaseException) and ExceptionGroup(BaseExceptionGroup, Exception).\n", | ||
| 498 | "# They are assignable to Exception.__cause__ and Exception.__context__,\n", | ||
| 499 | "# and they can be raised and handled as any exception with\n", | ||
| 500 | "# raise ExceptionGroup(...) and try: ... except ExceptionGroup: ... or\n", | ||
| 501 | "# raise BaseExceptionGroup(...) and try: ... except BaseExceptionGroup: ....\n", | ||
| 502 | "\n", | ||
| 503 | "my_dict = {\"test1\": \"foo\", \"test2\": \"bar\"}\n", | ||
| 504 | "\n", | ||
| 505 | "for key in (\"test3\", [1, 8]):\n", | ||
| 506 | " try:\n", | ||
| 507 | " result = my_dict[key]\n", | ||
| 508 | " except KeyError:\n", | ||
| 509 | " print(\"KeyError detected\")\n", | ||
| 510 | " except TypeError:\n", | ||
| 511 | " print(\"TypeError detected\")\n", | ||
| 512 | "\n", | ||
| 513 | "for key in (\"test3\", [1, 8]):\n", | ||
| 514 | " try:\n", | ||
| 515 | " result = my_dict[key]\n", | ||
| 516 | " except* (KeyError, TypeError) as eg:\n", | ||
| 517 | " for e in eg.exceptions:\n", | ||
| 518 | " print(f\"{type(e).__name__} detected\")\n", | ||
| 519 | " \n", | ||
| 520 | "\n", | ||
| 521 | "# PEP 678 – Enriching exceptions with notes\n", | ||
| 522 | "# BaseException gains a new method .add_note(note: str).\n", | ||
| 523 | "# If note is a string, .add_note(note) appends it to the __notes__ list, creating the attribute if it does not already exist.\n", | ||
| 524 | "# If note is not a string, .add_note() raises TypeError.\n", | ||
| 525 | "\n", | ||
| 526 | "try:\n", | ||
| 527 | " try:\n", | ||
| 528 | " raise TypeError(\"bad type\")\n", | ||
| 529 | " except Exception as e:\n", | ||
| 530 | " e.add_note(\"Really bad types at work\")\n", | ||
| 531 | " raise\n", | ||
| 532 | "except Exception as e:\n", | ||
| 533 | " print(f\"{e!s} - {e.__notes__}\")\n" | ||
| 534 | ] | ||
| 535 | }, | ||
| 536 | { | ||
| 537 | "cell_type": "markdown", | ||
| 538 | "id": "a3e0bcdd-69b8-4cb3-92e1-eeeb250b38ae", | ||
| 539 | "metadata": {}, | ||
| 540 | "source": [ | ||
| 541 | "## Other changes\n", | ||
| 542 | "\n", | ||
| 543 | "- starred unpacking expressions can now be used in `for` statements\n", | ||
| 544 | "\n", | ||
| 545 | "- 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", | ||
| 546 | "\n", | ||
| 547 | "- **PEP 682** – Format specifier for signed zero\n", | ||
| 548 | "\n", | ||
| 549 | "- *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", | ||
| 550 | "\n", | ||
| 551 | "- 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", | ||
| 552 | "\n", | ||
| 553 | "- added `datetime.UTC`, a convenience alias for `datetime.timezone.utc`" | ||
| 554 | ] | ||
| 555 | }, | ||
| 556 | { | ||
| 557 | "cell_type": "code", | ||
| 558 | "execution_count": 232, | ||
| 559 | "id": "f1f9977c-20f4-4bc1-9fa7-14acd0f16193", | ||
| 560 | "metadata": {}, | ||
| 561 | "outputs": [ | ||
| 562 | { | ||
| 563 | "name": "stdout", | ||
| 564 | "output_type": "stream", | ||
| 565 | "text": [ | ||
| 566 | "1\n", | ||
| 567 | "2\n", | ||
| 568 | "3\n", | ||
| 569 | "3\n", | ||
| 570 | "4\n", | ||
| 571 | "5\n", | ||
| 572 | "0.0\n", | ||
| 573 | "+0.0\n" | ||
| 574 | ] | ||
| 575 | } | ||
| 576 | ], | ||
| 577 | "source": [ | ||
| 578 | "# starred unpacking expressions can now be used in `for` statements\n", | ||
| 579 | "t1 = (1, 2, 3)\n", | ||
| 580 | "t2 = (3, 4, 5)\n", | ||
| 581 | "\n", | ||
| 582 | "for i in *t1, *t2:\n", | ||
| 583 | " print(i)\n", | ||
| 584 | "\n", | ||
| 585 | "\n", | ||
| 586 | "# PEP 682 – Format specifier for signed zero\n", | ||
| 587 | "# When z is present, negative zero (whether the original value or the result of rounding) will be normalized to positive zero\n", | ||
| 588 | "import decimal\n", | ||
| 589 | "\n", | ||
| 590 | "x = -.00001\n", | ||
| 591 | "print(f\"{x:z.1f}\")\n", | ||
| 592 | "\n", | ||
| 593 | "x = decimal.Decimal('-.00001')\n", | ||
| 594 | "print(f\"{x:+z.1f}\")\n" | ||
| 595 | ] | ||
| 596 | } | ||
| 597 | ], | ||
| 598 | "metadata": { | ||
| 599 | "kernelspec": { | ||
| 600 | "display_name": "Python 3 (ipykernel)", | ||
| 601 | "language": "python", | ||
| 602 | "name": "python3" | ||
| 603 | }, | ||
| 604 | "language_info": { | ||
| 605 | "codemirror_mode": { | ||
| 606 | "name": "ipython", | ||
| 607 | "version": 3 | ||
| 608 | }, | ||
| 609 | "file_extension": ".py", | ||
| 610 | "mimetype": "text/x-python", | ||
| 611 | "name": "python", | ||
| 612 | "nbconvert_exporter": "python", | ||
| 613 | "pygments_lexer": "ipython3", | ||
| 614 | "version": "3.11.0" | ||
| 615 | } | ||
| 616 | }, | ||
| 617 | "nbformat": 4, | ||
| 618 | "nbformat_minor": 5 | ||
| 619 | } | ||
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 @@ | |||
| 1 | { | ||
| 2 | "cells": [ | ||
| 3 | { | ||
| 4 | "cell_type": "markdown", | ||
| 5 | "id": "b3f102cb-0f33-43ad-a808-e8f3c171b370", | ||
| 6 | "metadata": {}, | ||
| 7 | "source": [ | ||
| 8 | "# Python 3.8\n", | ||
| 9 | "\n", | ||
| 10 | "Released on October 14th, 2019." | ||
| 11 | ] | ||
| 12 | }, | ||
| 13 | { | ||
| 14 | "cell_type": "markdown", | ||
| 15 | "id": "52f3a2f9-1270-48fe-a5c3-881574ec0191", | ||
| 16 | "metadata": {}, | ||
| 17 | "source": [ | ||
| 18 | "# Python 3.9\n", | ||
| 19 | "\n", | ||
| 20 | " Released on October 5th, 2020." | ||
| 21 | ] | ||
| 22 | }, | ||
| 23 | { | ||
| 24 | "cell_type": "markdown", | ||
| 25 | "id": "bac26435-89c5-4b89-af37-340fd9a9556c", | ||
| 26 | "metadata": {}, | ||
| 27 | "source": [ | ||
| 28 | "# Python 3.10\n", | ||
| 29 | "\n", | ||
| 30 | " Released on October 4, 2021." | ||
| 31 | ] | ||
| 32 | }, | ||
| 33 | { | ||
| 34 | "cell_type": "markdown", | ||
| 35 | "id": "ec96310b-2b8d-45f3-9cac-6ec33861483b", | ||
| 36 | "metadata": {}, | ||
| 37 | "source": [ | ||
| 38 | "# Python 3.11\n", | ||
| 39 | "\n" | ||
| 40 | ] | ||
| 41 | } | ||
| 42 | ], | ||
| 43 | "metadata": { | ||
| 44 | "kernelspec": { | ||
| 45 | "display_name": "Python 3 (ipykernel)", | ||
| 46 | "language": "python", | ||
| 47 | "name": "python3" | ||
| 48 | }, | ||
| 49 | "language_info": { | ||
| 50 | "codemirror_mode": { | ||
| 51 | "name": "ipython", | ||
| 52 | "version": 3 | ||
| 53 | }, | ||
| 54 | "file_extension": ".py", | ||
| 55 | "mimetype": "text/x-python", | ||
| 56 | "name": "python", | ||
| 57 | "nbconvert_exporter": "python", | ||
| 58 | "pygments_lexer": "ipython3", | ||
| 59 | "version": "3.8.10" | ||
| 60 | } | ||
| 61 | }, | ||
| 62 | "nbformat": 4, | ||
| 63 | "nbformat_minor": 5 | ||
| 64 | } | ||
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 @@ | |||
| 1216 | "\n", | 1216 | "\n", |
| 1217 | " - `__hash__`\n", | 1217 | " - `__hash__`\n", |
| 1218 | " \n", | 1218 | " \n", |
| 1219 | " - `__match_args__`\n", | ||
| 1220 | "\n", | ||
| 1219 | " - ...\n", | 1221 | " - ...\n", |
| 1220 | "\n", | 1222 | "\n", |
| 1221 | "- [Raymond Hettinger - Super considered super! - PyCon 2015](https://www.youtube.com/watch?v=EiOglTERPEo)\n", | 1223 | "- [Raymond Hettinger - Super considered super! - PyCon 2015](https://www.youtube.com/watch?v=EiOglTERPEo)\n", |
| @@ -1240,7 +1242,7 @@ | |||
| 1240 | "name": "python", | 1242 | "name": "python", |
| 1241 | "nbconvert_exporter": "python", | 1243 | "nbconvert_exporter": "python", |
| 1242 | "pygments_lexer": "ipython3", | 1244 | "pygments_lexer": "ipython3", |
| 1243 | "version": "3.8.10" | 1245 | "version": "3.11.0" |
| 1244 | } | 1246 | } |
| 1245 | }, | 1247 | }, |
| 1246 | "nbformat": 4, | 1248 | "nbformat": 4, |
