Novinky představené v Pythonu 3.15
Co se dozvíte v článku
- Novinky představené v Pythonu 3.15
- Instalace Pythonu 3.15 s využitím nástrojů pdm nebo uv
- Překlad Pythonu 3.15 ze zdrojových kódů
- Základní otestování právě přeloženého Pythonu 3.15
- Líný import balíčků
- Benchmark: skript, který importuje většinu standardních balíčků
- Líný import všech balíčků
- Porovnání výsledků
- Malé ohlédnutí za staršími verzemi Pythonu: vestavěný typ frozenset
- Nový vestavěný datový typ – frozendict
- Jak je tomu s neměnitelnými seznamy?
- Jaký význam má termín „immutable“ v jazyce Python?
- Rozbalení hodnot v programových konstrukcích využívajících generátorovou notaci
- Podpora pro rozbalení prvků v konstrukci generátorové notace seznamů
- Podpora pro rozbalení prvků v konstrukci generátorové notace množin
- Podpora pro rozbalení prvků v konstrukci generátorové notace slovníků
- Další vylepšení a rozšíření Pythonu 3.15
- Příloha: rezervovaná klíčová slova a „měkká klíčová slova“
- Repositář s demonstračními příklady
- Odkazy na Internetu
Přibližně před měsícem, konkrétně 9. října 2026, byl vydán Python 3.15. Jak je posledních několik let zvykem, přináší každá další verze Pythonu několik vylepšení, nové vlastnosti, ale i zrychlení interpretru. To pochopitelně platí i pro Python 3.15.
S nejvýznamnějšími vylepšeními a novými vlastnostmi se seznámíme v dnešním článku. Konkrétně si v dnešním článku a v článcích navazujících popíšeme následující změny a vylepšení:
| Číslo PEPu | Plný název PEPu |
|---|---|
| PEP 810 | Explicit lazy imports for faster startup times |
| PEP 814 | Add frozendict built-in type |
| PEP 661 | Add sentinel built-in type |
| PEP 798 | Unpacking in comprehensions |
| PEP 686 | Python now uses UTF-8 as the default encoding |
| PEP 829 | Package startup configuration files |
| PEP 799 | Tachyon: High frequency statistical sampling profiler |
| PEP 799 | A dedicated profiling package for organizing Python profiling tools |
| PEP 728 | TypedDict with typed extra items |
| PEP 747 | Annotating type forms with TypeForm |
| PEP 800 | Disjoint bases in the type system |
Pro úplnost si uveďme, jaké novinky byly představeny v předchozích verzích Pythonu 3.x:
| Verze Pythonu | Datum vydání této verze | Nejvýznamnější novinky |
|---|---|---|
| 3.0 | 3. prosince 2008 | |
| 3.1 | 27. června 2009 | |
| 3.2 | 20. února 2011 | |
| 3.3 | 29. září 2012 | |
| 3.4 | 16. března 2014 | |
| 3.5 | 13. září 2015 | sémantika pro async a await, operátor @, unpack |
| 3.6 | 23. prosince 2016 | f-řetězce, async-IO |
| 3.7 | 27. června 2018 | rezervovaná klíčová slova async a await |
| 3.8 | 14. října 2019 | mroží operátor, poziční parametry funkcí |
| 3.9 | 5. října 2020 | generické datové typy |
| 3.10 | 4. října 2021 | vylepšení zápisu datových typů |
| 3.11 | 24. října 2022 | skupiny výjimek |
| 3.12 | 2. října 2023 | klíčové slovo type + jeho sémantika |
| 3.13 | 7. října 2024 | experimentální podpora pro běh bez GIL |
| 3.14 | 7. října 2025 | t-řetězce, více interpretrů, možnost odstranění GILu, více barviček atd. |
| 3.15 | 9. října 2026 | téma dnešního článku |
Instalace Pythonu 3.15 s využitím nástrojů pdm nebo uv
Python 3.15 je možné nainstalovat několika způsoby. Nejjednodušší je situace v případě, že je tato verze Pythonu dostupná přímo v balíčcích vámi používané distribuce Linuxu. V takovém (ideálním) případě postačuje použít apt, dnf atd. a popř. si upravit alternatives.
Pokud Python 3.15 dostupný není (což je docela dobře možné), můžeme se ho pokusit nainstalovat s využitím nástrojů pdm nebo uv, které Python zvolené verze (nebo verzí) dokážou pro uživatele doinstalovat, a to bez nutnosti mít k dispozici administrátorská práva. Ukažme si celý postup při použití balíčku uv.
Zjištění, které verze Pythonu jsou již nainstalovány:
$ uv python list cpython-3.14.7-linux-x86_64-gnu /usr/bin/python3.14 cpython-3.14.7-linux-x86_64-gnu /usr/bin/python3 -> python3.14 cpython-3.14.7-linux-x86_64-gnu /usr/bin/python -> ./python3 cpython-3.14.0+freethreaded-linux-x86_64-gnu /usr/local/bin/python3.14t cpython-3.14.0+freethreaded-linux-x86_64-gnu /usr/local/bin/python3.14 cpython-3.14.0+freethreaded-linux-x86_64-gnu /usr/local/bin/python3 -> python3.14 cpython-3.14.0rc2-linux-x86_64-gnu .local/bin/python3.14 -> .local/share/uv/python/cpython-3.14.0rc2-linux-x86_64-gnu/bin/python3.14 cpython-3.14.0rc2-linux-x86_64-gnu .local/share/uv/python/cpython-3.14.0rc2-linux-x86_64-gnu/bin/python3.14 cpython-3.13.7-linux-x86_64-gnu .local/bin/python3.13 -> .local/share/uv/python/cpython-3.13.7-linux-x86_64-gnu/bin/python3.13 cpython-3.13.7-linux-x86_64-gnu .local/share/uv/python/cpython-3.13.7-linux-x86_64-gnu/bin/python3.13 cpython-3.11.16-linux-x86_64-gnu /usr/bin/python3.11
Instalace Pythonu 3.15:
$ uv python install 3.15
Pokud (až!) bude verze 3.15 dostupná pro váš operační systém a architekturu mikroprocesoru, měla by se vypsat následující zpráva:
Installed Python 3.15.0 in 3.74s + cpython-3.15.0-linux-x86_64-gnu (python3.15)
Překlad Pythonu 3.15 ze zdrojových kódů
Pokud si chcete vyzkoušet stabilní a oficiálně vydaný Python 3.15 a výše uvedený postup nefunguje, postačuje si ze stránek www.python.org/downloads stáhnout archiv (zkomprimovaný tarball), ten rozbalit a použít klasickou kombinaci příkazů (je nutné mít nainstalován překladač céčka, včetně jeho sady nástrojů, a navíc i nástroj make):
$ ./configure
Postup při generování konfiguračních souborů a skriptů:
checking build system type... x86_64-pc-linux-gnu checking host system type... x86_64-pc-linux-gnu checking for Python interpreter freezing... ./_bootstrap_python checking for python3.15... no checking for python3.15... no checking for python3.14... python3.14 checking Python for regen version... Python 3.14.0rc2 checking for pkg-config... /usr/bin/pkg-config checking pkg-config is at least version 0.9.0... yes ... ... ... config.status: pyconfig.h is unchanged configure: creating Modules/Setup.local configure: creating Makefile configure: If you want a release build with all stable optimizations active (PGO, etc), please run ./configure --enable-optimizations
Vlastní překlad lze spustit příkazem:
$ make
Ovšem mnohem rychlejší bude vynucení paralelního překladu. V mém případě se pokusím vytížit všech šestnáct jader:
$ make -j 16
Průběh překladu (jen krátká ukázka):
gcc -c -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -std=c11 -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wstrict-prototypes -Werror=implicit-function-declaration -fvisibility=hidden -I./Include/internal -I./Include/internal/mimalloc -I. -I./Include -DPy_BUILD_CORE -o Programs/python.o ./Programs/python.c
gcc -c -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -std=c11 -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wstrict-prototypes -Werror=implicit-function-declaration -fvisibility=hidden -I./Include/internal -I./Include/internal/mimalloc -I. -I./Include -DPy_BUILD_CORE -o Parser/token.o Parser/token.c
gcc -c -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -std=c11 -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wstrict-prototypes -Werror=implicit-function-declaration -fvisibility=hidden -I./Include/internal -I./Include/internal/mimalloc -I. -I./Include -DPy_BUILD_CORE -o Parser/pegen.o Parser/pegen.c
...
...
...
Written build/lib.linux-x86_64-3.15/_sysconfigdata__linux_x86_64-linux-gnu.py
Written build/lib.linux-x86_64-3.15/_sysconfig_vars__linux_x86_64-linux-gnu.json
./python -E -c 'import sys ; from sysconfig import get_platform ; print("%s-%d.%d" % (get_platform(), *sys.version_info[:2]))' >platform
./python -E ./Tools/build/generate-build-details.py `cat pybuilddir.txt`/build-details.json
gcc -shared Modules/_elementtree.o -o Modules/_elementtree.cpython-315-x86_64-linux-gnu.so
gcc -shared Modules/_testinternalcapi.o Modules/_testinternalcapi/test_lock.o Modules/_testinternalcapi/pytime.o Modules/_testinternalcapi/set.o Modules/_testinternalcapi/test_critical_sections.o Modules/_testinternalcapi/complex.o Modules/_testinternalcapi/interpreter.o Modules/_testinternalcapi/tuple.o -o Modules/_testinternalcapi.cpython-315-x86_64-linux-gnu.so
gcc -shared Modules/_ctypes/_ctypes_test.o -lm -o Modules/_ctypes_test.cpython-315-x86_64-linux-gnu.so
The necessary bits to build these optional modules were not found:
_dbm _decimal _gdbm
_tkinter _uuid readline
To find the necessary bits, look in configure.ac and config.log.
Checked 116 modules (37 built-in, 72 shared, 1 n/a on linux-x86_64, 0 disabled, 6 missing, 0 failed on import)
Výsledkem je spustitelný soubor python, který je již pěkný bumbrlíček (mimochodem: Python 1 se vešel na jedinou disketu):
$ ls -lah python -rwxr-xr-x. 1 ptisnovs ptisnovs 37M Oct 26 11:54 python
Velikost spustitelného binárního souboru s interpretrem lze zmenšit odstraněním symbolů příkazem strip:
$ strip python
Výsledek je již menší:
$ ls -lah python -rwxr-xr-x. 1 ptisnovs ptisnovs 6.2M Oct 26 11:57 python
Po překladu je možné Python nainstalovat příkazem (to ale není nutné, pokud si jen potřebujete otestovat základní funkcionalitu interpretru):
$ sudo make install
popř. je možné pouze symlinkovat výsledný spustitelný soubor python do ~/bin/ atd. (podle nastavení cest).
Základní otestování právě přeloženého Pythonu 3.15
Přeložili jsme vůbec korektní verzi Pythonu? To zjistíme snadno:
$ ./python --version Python 3.15.1
Následuje poslední test: spuštění interpretru Pythonu:
$ ./python Python 3.15.1 (main, Oct 26 2026, 11:54:26) [GCC 16.2.1 20260819 (Red Hat 16.2.1-2)] on linux Type "help", "copyright", "credits" or "license" for more information. >>>
Další volby a přepínače příkazové řádky se od Pythonu 3.14 prakticky nezměnily:
usage: ./python [option] ... [-c cmd | -m mod | file | -] [arg] ...
Options (and corresponding environment variables):
-b : issue warnings about converting bytes/bytearray to str and comparing
bytes/bytearray with str or bytes with int. (-bb: issue errors)
deprecated since 3.15 and will become no-op in 3.17.
-B : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x
-c cmd : program passed in as string (terminates option list)
-d : turn on parser debugging output (for experts only, only works on
debug builds); also PYTHONDEBUG=x
-E : ignore PYTHON* environment variables (such as PYTHONPATH)
-h : print this help message and exit (also -? or --help)
-i : inspect interactively after running script; forces a prompt even
if stdin does not appear to be a terminal; also PYTHONINSPECT=x
-I : isolate Python from the user's environment (implies -E, -P and -s)
-m mod : run library module as a script (terminates option list)
-O : remove assert and __debug__-dependent statements; add .opt-1 before
.pyc extension; also PYTHONOPTIMIZE=x
-OO : do -O changes and also discard docstrings; add .opt-2 before
.pyc extension
-P : don't prepend a potentially unsafe path to sys.path; also
PYTHONSAFEPATH
-q : don't print version and copyright messages on interactive startup
-s : don't add user site directory to sys.path; also PYTHONNOUSERSITE=x
-S : don't imply 'import site' on initialization
-u : force the stdout and stderr streams to be unbuffered;
this option has no effect on stdin; also PYTHONUNBUFFERED=x
-v : verbose (trace import statements); also PYTHONVERBOSE=x
can be supplied multiple times to increase verbosity
-V : print the Python version number and exit (also --version)
when given twice, print more information about the build
-W arg : warning control; arg is action:message:category:module:lineno
also PYTHONWARNINGS=arg
-x : skip first line of source, allowing use of non-Unix forms of #!cmd
-X opt : set implementation-specific option
--check-hash-based-pycs always|default|never:
control how Python invalidates hash-based .pyc files
--help-env: print help about Python environment variables and exit
--help-xoptions: print help about implementation-specific -X options and exit
--help-all: print complete help information and exit
Arguments:
file : program read from script file
- : program read from stdin (default; interactive mode if a tty)
arg ...: arguments passed to program in sys.argv[1:]
Líný import balíčků
Prvním vylepšením Pythonu, se kterým se v dnešním článku setkáme, je rozšíření sady klíčových slov o nové klíčové slovo lazy. Jedná se o takzvané „měkké“ klíčové slovo, tj. takové slovo, které má sice speciální význam, ale pouze v určitém kontextu. Do stejné kategorie patří i (taktéž relativně nová) klíčová slova match a case (viz přílohu). Ovšem vraťme se ke klíčovému slovu lazy. To má význam pouze společně s příkazem import resp. from a označuje se jím balíček, který má být naimportován „líně“:
lazy import balíček_x lazy from balíček_y import funkce_1, funkce_2, funkce_3
Interpret Pythonu se nepokusí takový balíček celý načíst a inicializovat, ale pouze si zapamatuje, že se balíček má načíst později – až ve chvíli, kdy bude skutečně použit. Počítá se s tím, že některé balíčky jsou jen importovány a nejsou nikdy skutečně použity. Příkladem jsou balíčky s typovými informacemi atd.
V jiném kontextu není lazy rezervovaným klíčovým slovem, což zajišťuje zpětnou kompatibilitu, například s následujícím skriptem (který je plně funkční i v Pythonu 3.15):
lazy = 42 print(lazy)
Benchmark: skript, který importuje většinu standardních balíčků
Abychom si ověřili, zda má slovo lazy nějaký efekt na rychlost vykonávání skriptů, jsem vytvořil poněkud umělý příklad (ostatně mnoho benchmarků je umělých). V něm je proveden import prakticky všech standardních balíčků dodávaných společně s Pythonem 3.15. Vynechal jsem pouze několik balíčků specifických pro Microsoft Windows a taktéž balíčků vyžadujících knihovnu Tk:
import abc import argparse import array import ast import asyncio import atexit import base64 import bdb import binascii import bisect import builtins import bz2 import calendar import cmath import cmd import code import codecs import codeop import collections import colorsys import compileall import compression import concurrent import concurrent.futures import concurrent.interpreters import configparser import contextlib import contextvars import copy import copyreg import csv import ctypes import ctypes.util import ctypes.wintypes import curses import curses.ascii import curses.has_key import curses.panel import curses.textpad import dataclasses import datetime import dbm import dbm.dumb import dbm.sqlite3 import decimal import difflib import dis import doctest import email import email.message import email.mime import email.parser import email.policy import email.quoprimime import email.utils import encodings import encodings.aliases import encodings.ascii import encodings.base64_codec import encodings.big5 import encodings.big5hkscs import encodings.bz2_codec import encodings.charmap import encodings.cp037 import encodings.cp1006 import encodings.cp1026 import encodings.cp1125 import encodings.cp1140 import encodings.cp1250 import encodings.cp1251 import encodings.cp1252 import encodings.cp1253 import encodings.cp1254 import encodings.cp1255 import encodings.cp1256 import encodings.cp1257 import encodings.cp1258 import encodings.cp273 import encodings.cp424 import encodings.cp437 import encodings.cp500 import encodings.cp720 import encodings.cp737 import encodings.cp775 import encodings.cp850 import encodings.cp852 import encodings.cp855 import encodings.cp856 import encodings.cp857 import encodings.cp858 import encodings.cp860 import encodings.cp861 import encodings.cp862 import encodings.cp863 import encodings.cp864 import encodings.cp865 import encodings.cp866 import encodings.cp869 import encodings.cp874 import encodings.cp875 import encodings.cp932 import encodings.cp949 import encodings.cp950 import encodings.euc_jis_2004 import encodings.euc_jisx0213 import encodings.euc_jp import encodings.euc_kr import encodings.gb18030 import encodings.gb2312 import encodings.gbk import encodings.hex_codec import encodings.hp_roman8 import encodings.hz import encodings.idna import encodings.iso2022_jp import encodings.iso2022_jp_1 import encodings.iso2022_jp_2 import encodings.iso2022_jp_2004 import encodings.iso2022_jp_3 import encodings.iso2022_jp_ext import encodings.iso2022_kr import encodings.iso8859_1 import encodings.iso8859_10 import encodings.iso8859_11 import encodings.iso8859_13 import encodings.iso8859_14 import encodings.iso8859_15 import encodings.iso8859_16 import encodings.iso8859_2 import encodings.iso8859_3 import encodings.iso8859_4 import encodings.iso8859_5 import encodings.iso8859_6 import encodings.iso8859_7 import encodings.iso8859_8 import encodings.iso8859_9 import encodings.johab import encodings.koi8_r import encodings.koi8_t import encodings.koi8_u import encodings.kz1048 import encodings.latin_1 import encodings.mac_arabic import encodings.mac_croatian import encodings.mac_cyrillic import encodings.mac_farsi import encodings.mac_greek import encodings.mac_iceland import encodings.mac_latin2 import encodings.mac_roman import encodings.mac_romanian import encodings.mac_turkish import encodings.palmos import encodings.ptcp154 import encodings.punycode import encodings.quopri_codec import encodings.raw_unicode_escape import encodings.rot_13 import encodings.shift_jis import encodings.shift_jis_2004 import encodings.shift_jisx0213 import encodings.tis_620 import encodings.undefined import encodings.unicode_escape import encodings.utf_16 import encodings.utf_16_be import encodings.utf_16_le import encodings.utf_32 import encodings.utf_32_be import encodings.utf_32_le import encodings.utf_7 import encodings.utf_8 import encodings.utf_8_sig import encodings.uu_codec import encodings.zlib_codec import ensurepip import ensurepip.__main__ import ensurepip._uninstall import enum import errno import faulthandler import fcntl import filecmp import fileinput import fnmatch import fractions import ftplib import functools import gc import genericpath import getopt import getpass import gettext import glob import graphlib import grp import gzip import hashlib import heapq import hmac import html import html.entities import html.parser import http import http.client import http.cookiejar import http.cookies import http.server import imaplib import importlib import importlib._abc import importlib._bootstrap import importlib._bootstrap_external import importlib.abc import importlib.machinery import importlib.metadata import importlib.metadata._adapters import importlib.metadata._collections import importlib.metadata._functools import importlib.metadata._itertools import importlib.metadata._meta import importlib.metadata._text import importlib.metadata.diagnose import importlib.readers import importlib.resources import importlib.resources._adapters import importlib.resources._common import importlib.resources._functional import importlib.resources._itertools import importlib.resources.abc import importlib.resources.readers import importlib.resources.simple import importlib.simple import importlib.util import inspect import io import ipaddress import itertools import json import json.__main__ import json.decoder import json.encoder import json.scanner import json.tool import keyword import linecache import locale import logging import logging.config import logging.handlers import lzma import mailbox import marshal import math import mimetypes import mmap import modulefinder import multiprocessing import multiprocessing.connection import multiprocessing.context import multiprocessing.dummy import multiprocessing.dummy.connection import multiprocessing.forkserver import multiprocessing.heap import multiprocessing.managers import multiprocessing.pool import multiprocessing.popen_fork import multiprocessing.popen_forkserver import multiprocessing.process import multiprocessing.queues import multiprocessing.reduction import multiprocessing.resource_sharer import multiprocessing.resource_tracker import multiprocessing.shared_memory import multiprocessing.sharedctypes import multiprocessing.spawn import multiprocessing.synchronize import multiprocessing.util import netrc import numbers import opcode import operator import optparse import os import os.path import pathlib import pathlib._os import pathlib.types import pdb import pickle import pickletools import pkgutil import platform import plistlib import poplib import posix import posixpath import pprint import pstats import pty import pwd import py_compile import pyclbr import pydoc import pydoc_data import pydoc_data.topics import pyexpat import pyexpat.errors import pyexpat.model import queue import quopri import random import re import re._casefix import re._compiler import re._constants import re._parser import reprlib import resource import rlcompleter import runpy import sched import secrets import select import selectors import shelve import shlex import shutil import signal import site import smtplib import socket import socketserver import sqlite3 import sqlite3.__main__ import sqlite3.dbapi2 import sqlite3.dump import ssl import stat import statistics import string import string.templatelib import stringprep import struct import subprocess import symtable import sys import sysconfig import sysconfig.__main__ import syslog import tabnanny import tarfile import tempfile import termios import textwrap import threading import time import timeit import token import tokenize import tomllib import tomllib._parser import tomllib._re import tomllib._types import trace import traceback import tracemalloc import tty import types import typing import unicodedata import urllib import urllib.error import urllib.parse import urllib.request import urllib.response import urllib.robotparser import uuid import warnings import wave import weakref import webbrowser import wsgiref import wsgiref.handlers import wsgiref.headers import wsgiref.simple_server import wsgiref.types import wsgiref.util import wsgiref.validate import xml import xml.dom import xml.etree import xml.parsers import xml.parsers.expat import xml.sax import xml.sax.handler import xml.sax.saxutils import xml.sax.xmlreader import xmlrpc import xmlrpc.client import xmlrpc.server import zipapp import zipfile import zipimport import zlib import zoneinfo
Líný import všech balíčků
Předchozí skript nyní upravíme tak, aby před každým klíčovým slovem import byl zapsán modifikátor lazy. Tím se v Pythonu 3.15 dosáhne toho, že si interpret zapamatuje, že má provést import, ale provede ho až později – když to bude nezbytně nutné (nebo nikdy, pokud to nutné nebude):
lazy import abc lazy import argparse lazy import array lazy import ast lazy import asyncio lazy import atexit lazy import base64 lazy import bdb lazy import binascii lazy import bisect lazy import builtins lazy import bz2 lazy import calendar lazy import cmath lazy import cmd lazy import code lazy import codecs lazy import codeop lazy import collections lazy import colorsys lazy import compileall lazy import compression lazy import concurrent lazy import concurrent.futures lazy import concurrent.interpreters lazy import configparser lazy import contextlib lazy import contextvars lazy import copy lazy import copyreg lazy import csv lazy import ctypes lazy import ctypes.util lazy import ctypes.wintypes lazy import curses lazy import curses.ascii lazy import curses.has_key lazy import curses.panel lazy import curses.textpad lazy import dataclasses lazy import datetime lazy import dbm lazy import dbm.dumb lazy import dbm.sqlite3 lazy import decimal lazy import difflib lazy import dis lazy import doctest lazy import email lazy import email.message lazy import email.mime lazy import email.parser lazy import email.policy lazy import email.quoprimime lazy import email.utils lazy import encodings lazy import encodings.aliases lazy import encodings.ascii lazy import encodings.base64_codec lazy import encodings.big5 lazy import encodings.big5hkscs lazy import encodings.bz2_codec lazy import encodings.charmap lazy import encodings.cp037 lazy import encodings.cp1006 lazy import encodings.cp1026 lazy import encodings.cp1125 lazy import encodings.cp1140 lazy import encodings.cp1250 lazy import encodings.cp1251 lazy import encodings.cp1252 lazy import encodings.cp1253 lazy import encodings.cp1254 lazy import encodings.cp1255 lazy import encodings.cp1256 lazy import encodings.cp1257 lazy import encodings.cp1258 lazy import encodings.cp273 lazy import encodings.cp424 lazy import encodings.cp437 lazy import encodings.cp500 lazy import encodings.cp720 lazy import encodings.cp737 lazy import encodings.cp775 lazy import encodings.cp850 lazy import encodings.cp852 lazy import encodings.cp855 lazy import encodings.cp856 lazy import encodings.cp857 lazy import encodings.cp858 lazy import encodings.cp860 lazy import encodings.cp861 lazy import encodings.cp862 lazy import encodings.cp863 lazy import encodings.cp864 lazy import encodings.cp865 lazy import encodings.cp866 lazy import encodings.cp869 lazy import encodings.cp874 lazy import encodings.cp875 lazy import encodings.cp932 lazy import encodings.cp949 lazy import encodings.cp950 lazy import encodings.euc_jis_2004 lazy import encodings.euc_jisx0213 lazy import encodings.euc_jp lazy import encodings.euc_kr lazy import encodings.gb18030 lazy import encodings.gb2312 lazy import encodings.gbk lazy import encodings.hex_codec lazy import encodings.hp_roman8 lazy import encodings.hz lazy import encodings.idna lazy import encodings.iso2022_jp lazy import encodings.iso2022_jp_1 lazy import encodings.iso2022_jp_2 lazy import encodings.iso2022_jp_2004 lazy import encodings.iso2022_jp_3 lazy import encodings.iso2022_jp_ext lazy import encodings.iso2022_kr lazy import encodings.iso8859_1 lazy import encodings.iso8859_10 lazy import encodings.iso8859_11 lazy import encodings.iso8859_13 lazy import encodings.iso8859_14 lazy import encodings.iso8859_15 lazy import encodings.iso8859_16 lazy import encodings.iso8859_2 lazy import encodings.iso8859_3 lazy import encodings.iso8859_4 lazy import encodings.iso8859_5 lazy import encodings.iso8859_6 lazy import encodings.iso8859_7 lazy import encodings.iso8859_8 lazy import encodings.iso8859_9 lazy import encodings.johab lazy import encodings.koi8_r lazy import encodings.koi8_t lazy import encodings.koi8_u lazy import encodings.kz1048 lazy import encodings.latin_1 lazy import encodings.mac_arabic lazy import encodings.mac_croatian lazy import encodings.mac_cyrillic lazy import encodings.mac_farsi lazy import encodings.mac_greek lazy import encodings.mac_iceland lazy import encodings.mac_latin2 lazy import encodings.mac_roman lazy import encodings.mac_romanian lazy import encodings.mac_turkish lazy import encodings.palmos lazy import encodings.ptcp154 lazy import encodings.punycode lazy import encodings.quopri_codec lazy import encodings.raw_unicode_escape lazy import encodings.rot_13 lazy import encodings.shift_jis lazy import encodings.shift_jis_2004 lazy import encodings.shift_jisx0213 lazy import encodings.tis_620 lazy import encodings.undefined lazy import encodings.unicode_escape lazy import encodings.utf_16 lazy import encodings.utf_16_be lazy import encodings.utf_16_le lazy import encodings.utf_32 lazy import encodings.utf_32_be lazy import encodings.utf_32_le lazy import encodings.utf_7 lazy import encodings.utf_8 lazy import encodings.utf_8_sig lazy import encodings.uu_codec lazy import encodings.zlib_codec lazy import ensurepip lazy import ensurepip.__main__ lazy import ensurepip._uninstall lazy import enum lazy import errno lazy import faulthandler lazy import fcntl lazy import filecmp lazy import fileinput lazy import fnmatch lazy import fractions lazy import ftplib lazy import functools lazy import gc lazy import genericpath lazy import getopt lazy import getpass lazy import gettext lazy import glob lazy import graphlib lazy import grp lazy import gzip lazy import hashlib lazy import heapq lazy import hmac lazy import html lazy import html.entities lazy import html.parser lazy import http lazy import http.client lazy import http.cookiejar lazy import http.cookies lazy import http.server lazy import imaplib lazy import importlib lazy import importlib._abc lazy import importlib._bootstrap lazy import importlib._bootstrap_external lazy import importlib.abc lazy import importlib.machinery lazy import importlib.metadata lazy import importlib.metadata._adapters lazy import importlib.metadata._collections lazy import importlib.metadata._functools lazy import importlib.metadata._itertools lazy import importlib.metadata._meta lazy import importlib.metadata._text lazy import importlib.metadata.diagnose lazy import importlib.readers lazy import importlib.resources lazy import importlib.resources._adapters lazy import importlib.resources._common lazy import importlib.resources._functional lazy import importlib.resources._itertools lazy import importlib.resources.abc lazy import importlib.resources.readers lazy import importlib.resources.simple lazy import importlib.simple lazy import importlib.util lazy import inspect lazy import io lazy import ipaddress lazy import itertools lazy import json lazy import json.__main__ lazy import json.decoder lazy import json.encoder lazy import json.scanner lazy import json.tool lazy import keyword lazy import linecache lazy import locale lazy import logging lazy import logging.config lazy import logging.handlers lazy import lzma lazy import mailbox lazy import marshal lazy import math lazy import mimetypes lazy import mmap lazy import modulefinder lazy import multiprocessing lazy import multiprocessing.connection lazy import multiprocessing.context lazy import multiprocessing.dummy lazy import multiprocessing.dummy.connection lazy import multiprocessing.forkserver lazy import multiprocessing.heap lazy import multiprocessing.managers lazy import multiprocessing.pool lazy import multiprocessing.popen_fork lazy import multiprocessing.popen_forkserver lazy import multiprocessing.process lazy import multiprocessing.queues lazy import multiprocessing.reduction lazy import multiprocessing.resource_sharer lazy import multiprocessing.resource_tracker lazy import multiprocessing.shared_memory lazy import multiprocessing.sharedctypes lazy import multiprocessing.spawn lazy import multiprocessing.synchronize lazy import multiprocessing.util lazy import netrc lazy import numbers lazy import opcode lazy import operator lazy import optparse lazy import os lazy import os.path lazy import pathlib lazy import pathlib._os lazy import pathlib.types lazy import pdb lazy import pickle lazy import pickletools lazy import pkgutil lazy import platform lazy import plistlib lazy import poplib lazy import posix lazy import posixpath lazy import pprint lazy import pstats lazy import pty lazy import pwd lazy import py_compile lazy import pyclbr lazy import pydoc lazy import pydoc_data lazy import pydoc_data.topics lazy import pyexpat lazy import pyexpat.errors lazy import pyexpat.model lazy import queue lazy import quopri lazy import random lazy import re lazy import re._casefix lazy import re._compiler lazy import re._constants lazy import re._parser lazy import reprlib lazy import resource lazy import rlcompleter lazy import runpy lazy import sched lazy import secrets lazy import select lazy import selectors lazy import shelve lazy import shlex lazy import shutil lazy import signal lazy import site lazy import smtplib lazy import socket lazy import socketserver lazy import sqlite3 lazy import sqlite3.__main__ lazy import sqlite3.dbapi2 lazy import sqlite3.dump lazy import ssl lazy import stat lazy import statistics lazy import string lazy import string.templatelib lazy import stringprep lazy import struct lazy import subprocess lazy import symtable lazy import sys lazy import sysconfig lazy import sysconfig.__main__ lazy import syslog lazy import tabnanny lazy import tarfile lazy import tempfile lazy import termios lazy import textwrap lazy import threading lazy import time lazy import timeit lazy import token lazy import tokenize lazy import tomllib lazy import tomllib._parser lazy import tomllib._re lazy import tomllib._types lazy import trace lazy import traceback lazy import tracemalloc lazy import tty lazy import types lazy import typing lazy import unicodedata lazy import urllib lazy import urllib.error lazy import urllib.parse lazy import urllib.request lazy import urllib.response lazy import urllib.robotparser lazy import uuid lazy import warnings lazy import wave lazy import weakref lazy import webbrowser lazy import wsgiref lazy import wsgiref.handlers lazy import wsgiref.headers lazy import wsgiref.simple_server lazy import wsgiref.types lazy import wsgiref.util lazy import wsgiref.validate lazy import xml lazy import xml.dom lazy import xml.etree lazy import xml.parsers lazy import xml.parsers.expat lazy import xml.sax lazy import xml.sax.handler lazy import xml.sax.saxutils lazy import xml.sax.xmlreader lazy import xmlrpc lazy import xmlrpc.client lazy import xmlrpc.server lazy import zipapp lazy import zipfile lazy import zipimport lazy import zlib lazy import zoneinfo
Porovnání výsledků
Oba skripty spustíme v interpretru Pythonu 3.15 a budeme měřit čas jejich dokončení.
Nejprve změříme dobu, kterou trvá dokončení prvního skriptu:
$ time ./python normal_import.py real 0m0.480s user 0m0.434s sys 0m0.040s
Stejným způsobem změříme dobu trvání skriptu druhého:
$ time ./python lazy_import.py real 0m0.030s user 0m0.022s sys 0m0.008s
V tomto (extrémním) případě je tedy druhý skript 16× rychlejší. Ovšem skutečně se jedná o extrémní příklad, který byl zvolen z toho důvodu, aby se ukázalo, že slovo lazy má skutečně nějaký efekt.
Malé ohlédnutí za staršími verzemi Pythonu: vestavěný typ frozenset
Již v předchozích verzích programovacího jazyka Python bylo možné využít vestavěný datový typ nazvaný frozenset, což je varianta množiny, která je neměnitelná (immutable), pochopitelně se všemi přednostmi i zápory, které to přináší. Zápis konstrukce „zamrzlé množiny“ je snadný a může vypadat následovně:
# Supported attachment content types
ATTACHMENT_CONTENT_TYPES = frozenset(
{
"text/plain",
"application/json",
"application/yaml",
"application/xml",
"image/jpeg",
"image/png",
"image/webp",
}
)
Popř. můžeme tento zápis doplnit o typové informace (záleží, jakou „štábní kulturu“ váš projekt dodržuje):
# Supported attachment content types
ATTACHMENT_CONTENT_TYPES: Final[frozenset[str]] = frozenset(
{
"text/plain",
"application/json",
"application/yaml",
"application/xml",
"image/jpeg",
"image/png",
"image/webp",
}
)
O tom, že je takto definovaná množina skutečně neměnitelná, se můžeme snadno přesvědčit pokusem o přidání nového prvku (či odebrání prvku atd.):
ATTACHMENT_CONTENT_TYPES = frozenset(
{
"text/plain",
"application/json",
"application/yaml",
"application/xml",
"image/jpeg",
"image/webp",
}
)
ATTACHMENT_CONTENT_TYPES.add("image/png")
Interpret Pythonu tyto operace nepovolí provést:
$ python frozen_set.py
Traceback (most recent call last):
File "/home/ptisnovs/src/most-popular-python-libs/python3.15/frozen_set.py", line 5, in <module>
ATTACHMENT_CONTENT_TYPES.add("image/png")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'frozenset' object has no attribute 'add'
Další operace s neměnitelnými množinami jsou ovšem plně podporovány. Například se jedná o operaci sjednocení množin:
DOCUMENT_CONTENT_TYPES: Final[frozenset[str]] = frozenset(
{
"text/plain",
"application/json",
"application/yaml",
"application/xml",
}
)
IMAGE_CONTENT_TYPES: Final[frozenset[str]] = frozenset(
{
"image/jpeg",
"image/png",
"image/webp",
}
)
ATTACHMENT_CONTENT_TYPES = DOCUMENT_CONTENT_TYPES | IMAGE_CONTENT_TYPES
print(ATTACHMENT_CONTENT_TYPES)
Výsledek:
frozenset({'application/yaml', 'text/plain', 'application/xml', 'image/webp', 'image/jpeg', 'application/json', 'image/png'})
Nový vestavěný datový typ – frozendict
Do Pythonu 3.15 byl přidán vestavěný datový typ, který sice již vznikl v minulosti, ale bylo ho nutné explicitně importovat. Jedná se o neměnitelný slovník (frozendict). V předchozích verzích Pythonu se s tímto slovníkem pracovalo následovně (povšimněte si explicitního importu):
from frozendict import frozendict d = frozendict(x=1, y=2, z="foo") print(d)
V Pythonu 3.15 je možné import vynechat a použít tak vestavěný datový typ se stejným jménem:
d = frozendict(x=1, y=2, z="foo") print(d)
Výsledky:
frozendict({'x': 1, 'y': 2, 'z': 'foo'})
A vzhledem k tomu, že je tento slovník skutečně neměnitelný, povede snaha o modifikaci jeho prvku, přidání prvku nebo vymazání prvku, k běhové chybě:
d = frozendict(x=1, y=2, z="foo") print(d) d["a"] = "bar" del d["z"]
frozendict({'x': 1, 'y': 2, 'z': 'foo'})
Traceback (most recent call last):
File "/tmp/ramdisk/Python-3.15.1/frozen_dict_2.py", line 4, in <module>
d["a"] = "bar"
~^^^^^
TypeError: 'frozendict' object does not support item assignment
Podobně jako v případě typu frozenset i v případě neměnitelných slovníků platí, že frozendict je současně názvem typu i konstruktorem:
d: frozendict = frozendict(x=1, y=2, z="foo") print(d) d["a"] = "bar" del d["z"]
Neměnitelný slovník lze vytvořit ze slovníku běžného. Co se týče pořadí prvků (při iteraci), je v obou případech zachování jejich pořadí:
planets = frozendict({
"Mercury": 57_910_000,
"Venus": 108_200_000,
"Earth": 149_600_000,
"Mars": 227_900_000,
"Jupiter": 778_500_000,
"Saturn": 1_434_000_000,
"Uranus": 2_871_000_000,
"Neptune": 4_495_000_000,
})
d = frozendict(planets)
for name, distance in d.items():
print(name, distance)
Výsledky:
Mercury 57910000 Venus 108200000 Earth 149600000 Mars 227900000 Jupiter 778500000 Saturn 1434000000 Uranus 2871000000 Neptune 4495000000
Jak je tomu s neměnitelnými seznamy?
Množiny set mají svoji neměnitelnou variantu nazvanou frozenset a nově mají i slovníky (dict) standardní neměnitelnou variantu nazvanou frozendict. Možná si někdo položí otázku, jak je tomu se seznamy (list)? Typ frozenlist skutečně prozatím neexistuje, i když se už několik vývojářů snažilo o jeho přidání – a v registru balíčků PyPI nalezneme i balíčky s jeho implementací. Je tomu tak z toho důvodu, že v Pythonu je k dispozici datový typ n-tice (tuple). Tento datový typ je sice z hlediska sémantiky „přetížen“ (využívá se v několika oblastech pro několik zcela rozdílných účelů), ovšem je ho možné použít i ve funkci plnohodnotných neměnitelných seznamů:
x: tuple[str, ...] = ("foo", "bar", "baz")
print(x)
x[1] = "xyzzy"
print(x)
Modifikace n-tice není možná:
('foo', 'bar', 'baz')
Traceback (most recent call last):
File "/tmp/ramdisk/Python-3.15.1/tuple_1.py", line 4, in <module>
x[1] = "xyzzy"
~^^^
TypeError: 'tuple' object does not support item assignment
Taktéž není povoleno přidávání prvků do n-tice nebo jejich mazání:
x: tuple[str, ...] = ("foo", "bar", "baz")
print(x)
x.append("xyzzy")
print(x)
Výsledky:
('foo', 'bar', 'baz')
Traceback (most recent call last):
File "/tmp/ramdisk/Python-3.15.1/tuple_2.py", line 4, in <module>
x.append("xyzzy")
^^^^^^^^
AttributeError: 'tuple' object has no attribute 'append'. Did you mean to use a 'list' object?
Jaký význam má termín „immutable“ v jazyce Python?
V předchozích kapitolách jsem několikrát použil termín neměnitelnost (immutability). Ten se ovšem v souvislosti s datovými typy (a především s kontejnery) používá ve dvou významech:
- Úplná neměnitelnost jak kontejneru (nelze přidávat ani mazat prvky), tak i hodnot v něm uložených (prvky nelze modifikovat).
- Neměnitelný je jen kontejner (opět: nelze přidávat ani mazat prvky), ovšem samotné prvky mohou být měnitelné. To záleží na jejich typu (numerické hodnoty a řetězce jsou neměnitelné), vložené seznamy měnitelné atd.
V Pythonu je použit druhý způsob, což si ostatně můžeme velmi snadno ověřit. Například n-tice je neměnitelná, ale modifikovat lze její prvek (typu seznam):
t = ("foo", "bar", "baz", [])
print(t)
t[3].append(1)
t[3].append(2)
t[3].append(3)
t[3].append(3)
print(t)
Z výsledků je patrné, že seznam lze skutečně modifikovat:
('foo', 'bar', 'baz', [])
('foo', 'bar', 'baz', [1, 2, 3, 3])
Podívejme se na složitější (poněkud umělý) příklad, ve kterém se používá neměnitelný slovník, jehož prvky jsou seznamy. I tyto seznamy lze modifikovat:
planets = frozendict({
"Mercury": [57_910_000],
"Venus": [108_200_000],
"Earth": [149_600_000],
"Mars": [227_900_000],
"Jupiter": [778_500_000],
"Saturn": [1_434_000_000],
"Uranus": [2_871_000_000],
"Neptune": [4_495_000_000],
})
d = frozendict(planets)
for name, distance in d.items():
print(name, distance)
print("-"*60)
d["Mercury"][0] = 10000
d["Earth"].append("foo")
for name, distance in d.items():
print(name, distance)
Výsledky opět ukazují modifikovatelnost prvků neměnitelného seznamu:
Mercury [57910000] Venus [108200000] Earth [149600000] Mars [227900000] Jupiter [778500000] Saturn [1434000000] Uranus [2871000000] Neptune [4495000000] ------------------------------------------------------------ Mercury [10000] Venus [108200000] Earth [149600000, 'foo'] Mars [227900000] Jupiter [778500000] Saturn [1434000000] Uranus [2871000000] Neptune [4495000000]
Rozbalení hodnot v programových konstrukcích využívajících generátorovou notaci
V Pythonu je pro seznamy, slovníky i množiny podporována syntaktická konstrukce označovaná jako generátorová notace. Ta umožňuje zápis „funkcionálních“ operací typu map a filter idiomatickým způsobem (pro Python).
Ukažme si příklad zápisu generátorové notace pro seznamy:
seznam = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] seznam2 = [item * 2 for item in seznam] seznam3 = [item for item in seznam if item % 3 == 0] print(seznam) print(seznam2) print(seznam3)
Podobným způsobem lze zapsat generátorovou notaci pro množiny:
s = {x*2 for x in range(11)}
print(s)
Generátorová notace slovníku se zapisuje následujícím způsobem:
d = {x: x*2 for x in range(11) if x%3 != 0}
print(d)
V Pythonu 3.15 byly tyto programové konstrukce rozšířeny o možnost rozbalení jednotlivých prvků, které jsou ze seznamu, množiny atd. získávány. To například umožňuje zploštění (flattening) datových struktur atd. Nový zápis využívá znaků * a **. V navazujících kapitolách budou uvedeny praktické ukázky.
Podpora pro rozbalení prvků v konstrukci generátorové notace seznamů
V následujícím skriptu je definován seznam, jehož prvky obsahují taktéž seznamy (s různým počtem prvků). Na dalším řádku je zapsána konstrukce generátorové notace seznamu, která v tomto případě pouze transformuje vstupní seznam do seznamu nového. Prvky tohoto nového seznamu jsou pouze zkopírovány ze seznamu původního, což si ověříme postupným výpisem všech prvků:
lists = [["foo"], ["bar", "baz"], ["x", "y", "z"]]
x = [L for L in lists]
for i, item in enumerate(x):
print(i, item)
Výsledek:
0 ['foo'] 1 ['bar', 'baz'] 2 ['x', 'y', 'z']
Pokud by bylo zapotřebí prvky původního seznamu rozbalit a následně je vložit v rozbalené podobě do seznamu výsledného, je nutné v Pythonu 3.14 (i ve starších verzích Pythonu) použít například následující zápis využívající generátorovou notaci:
lists = [["foo"], ["bar", "baz"], ["x", "y", "z"]]
x = [item for L in lists for item in L]
for i, item in enumerate(x):
print(i, item)
Výsledek:
0 foo 1 bar 2 baz 3 x 4 y 5 z
V Pythonu 3.15 je podporován kratší a do jisté míry i čitelnější zápis, který vypadá následovně:
lists = [["foo"], ["bar", "baz"], ["x", "y", "z"]]
x = [*L for L in lists]
for i, item in enumerate(x):
print(i, item)
Výsledek bude totožný s předchozí verzí skriptu:
0 foo 1 bar 2 baz 3 x 4 y 5 z
values = [1, 2, 3] print(*values)
Podpora pro rozbalení prvků v konstrukci generátorové notace množin
Podobným způsobem můžeme řešit „zploštění“ seznamu množin do jediné množiny. Zápis této operace bez využití nových vlastností Pythonu 3.15 by mohl vypadat následovně:
sets = [{"foo"}, {"bar", "baz"}, {"x", "y", "z"}]
x = {x for S in sets for x in S}
for i, item in enumerate(x):
print(i, item)
Výsledky:
0 baz 1 foo 2 x 3 bar 4 z 5 y
Nová konstrukce podporovaná Pythonem 3.15 umožňuje zápis zkrátit a zpřehlednit:
sets = [{"foo"}, {"bar", "baz"}, {"x", "y", "z"}]
x = {*S for S in sets}
for i, item in enumerate(x):
print(i, item)
Opět se podívejme na výsledky, které mohou vypadat následovně:
0 bar 1 foo 2 y 3 z 4 x 5 baz
Pro úplnost se ještě podívejme na chování skriptu v případě, že původní seznam obsahuje množiny, které mají stejné prvky:
sets = [{"foo", "bar"}, {"bar", "baz"}, {"foo", "baz"}]
x = {*S for S in sets}
for i, item in enumerate(x):
print(i, item)
Výsledkem je tato množina:
0 foo 1 baz 2 bar
Podpora pro rozbalení prvků v konstrukci generátorové notace slovníků
Práce se slovníky je v několika ohledech odlišná od zpracování seznamů a množin. Největší rozdíl spočívá v tom, že (většinou) musíme explicitně zpracovávat nejenom hodnoty uložené do slovníku, ale i klíče, ke kterým jsou tyto hodnoty přiřazeny. To se projevuje i v odlišném způsobu zápisu rozbalení prvků v generátorové notaci.
Opět se podívejme na jednoduchý příklad, ve kterém budeme spojovat několik slovníků (uložených například v seznamu) do slovníku jediného. V předchozích verzích Pythonu by mohl zápis s využitím generátorové notace vypadat například takto:
dicts = [{"foo": 1}, {"bar": 2}, {"baz": 3}, {"foo": 4}]
x = {k: v for D in dicts for k,v in D.items()}
for key, value in x.items():
print(key, value)
Z vypsaných výsledků je patrné, že došlo k přepisu první dvojice klíč-hodnota dvojicí poslední (foo:4):
foo 4 bar 2 baz 3
Nový způsob zápisu používá v generátorové notaci dvě hvězdičky (což odpovídá expanzi slovníku při volání funkce s keyword parametry – viz další odstavec):
dicts = [{"foo": 1}, {"bar": 2}, {"baz": 3}, {"foo": 4}]
x = {**D for D in dicts}
for key, value in x.items():
print(key, value)
Opět pro jistotu zkontrolujeme chování tohoto skriptu. Výsledný slovník by měl vypadat následovně:
foo 4 bar 2 baz 3
V předchozím odstavci jsem zmínil expanzi slovníku při volání funkce s keyword parametry. Jedná se o následující konstrukci (existuje i ve starších verzích Pythonu):
def login(name, password):
print(name, password)
data = {"name": "root", "password": "nbusr123"}
greet(**data)
Otázka na závěr. Jaké zprávy vypíše následující skript a proč?
dicts = [{"foo": 1, "bar": 1}, {"bar": 2, "baz": 2}, {"baz": 3, "foo": 4}]
x = {**D for D in dicts}
for key, value in x.items():
print(key, value)
Další vylepšení a rozšíření Pythonu 3.15
V Pythonu 3.15 nalezneme i některá další vylepšení a rozšíření. Jedná se především o vylepšení profileru, úpravy just-in-time (JIT) překladače, vylepšení chybových hlášení (ta pomohou nejenom vývojářům, ale i AI agentům) atd. Těmito vylepšeními se budeme podrobněji zabývat v navazujícím článku, protože především modifikace provedené v JIT překladači mohou poměrně výrazně urychlit skripty i větší aplikace naprogramované v Pythonu. A pochopitelně nezapomeneme ani na porovnání celkové rychlosti Pythonu 3.15 v porovnání s jeho staršími verzemi.
Příloha: rezervovaná klíčová slova a „měkká klíčová slova“
V předchozím textu jsme si mj. popsali i nové klíčové slovo lazy, které patří mezi klíčová slova platná pouze v rámci určitého kontextu (zde konkrétně společně s příkazem import). Klíčová slova jsou dostupná i přímo v běžícím programu (resp. v interpretru Pythonu). Následující příkaz ukazuje, jak vypsat skutečná rezervovaná klíčová slova i jak zjistit, jestli nějaký řetězec reprezentuje klíčové slovo nebo jen „měkké“ klíčové slovo:
import keyword
print(keyword.kwlist)
print(keyword.iskeyword("match"))
print(keyword.issoftkeyword("match"))
Výsledek pro Python 3.15 bude stejný, jako například i pro Python 3.14:
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] False True
Podobně můžeme otestovat řetězec „lazy“:
import keyword
print(keyword.kwlist)
print(keyword.iskeyword("lazy"))
print(keyword.issoftkeyword("lazy"))
Předchozí verze Pythonu (<=3.14) vypíšou tyto informace (včetně False na konci):
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] False False
Naproti tomu Python 3.15 na konci vypíše hodnotu True:
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] False True
Repositář s demonstračními příklady
Demonstrační příklady vytvořené pro Python verze 3.15 a popsané v dnešním článku najdete v repositáři https://github.com/tisnik/most-popular-python-libs/. Následují odkazy na jednotlivé příklady:
Odkazy na Internetu
- Python 3.15.0
https://www.python.org/downloads/release/python-3150/ - Python 3.14.0
https://test.python.org/downloads/release/python-3140/ - PEP 765 – Disallow return/break/continue that exit a finally block
https://peps.python.org/pep-0765/ - PEP 758 – Allow except and except* expressions without parentheses
https://peps.python.org/pep-0758/ - stdlib-list
https://github.com/pypi/stdlib-list - What’s new in Python 3.15 (official)
https://docs.python.org/3/whatsnew/3.15.html - What’s new in Python 3.14 (official)
https://docs.python.org/3/whatsnew/3.14.html - What’s New In Python 3.13 (official)
https://docs.python.org/3/whatsnew/3.13.html - What’s New In Python 3.12 (official)
https://docs.python.org/3/whatsnew/3.12.html - What’s New In Python 3.11 (official)
https://docs.python.org/3/whatsnew/3.11.html - What’s New In Python 3.12
https://dev.to/mahiuddindev/python-312-4n43 - PEP 698 – Override Decorator for Static Typing
https://peps.python.org/pep-0698/ - PEP 484 – Type Hints
https://www.python.org/dev/peps/pep-0484/ - What’s New In Python 3.5
https://docs.python.org/3.5/whatsnew/3.5.html - 26.1. typing — Support for type hints
https://docs.python.org/3.5/library/typing.html#module-typing - Type Hints – Guido van Rossum – PyCon 2015 (youtube)
https://www.youtube.com/watch?v=2wDvzy6Hgxg - Python 3.5 is on its way
https://lwn.net/Articles/650904/ - Type hints
https://lwn.net/Articles/640359/ - Stránka projektu PDM
https://pdm.fming.dev/latest/ - PDF na GitHubu
https://github.com/pdm-project/pdm - PEP 582 – Python local packages directory
https://peps.python.org/pep-0582/ - PDM na PyPi
https://pypi.org/project/pdm/ - Which Python package manager should you use?
https://towardsdatascience.com/which-python-package-manager-should-you-use-d0fd0789a250 - How to Use PDM to Manage Python Dependencies without a Virtual Environment
https://www.youtube.com/watch?v=qOIWNSTYfcc - What are the best Python package managers?
https://www.slant.co/topics/2666/~best-python-package-managers - PEP 621 – Storing project metadata in pyproject.toml
https://peps.python.org/pep-0621/ - Pick a Python Lockfile and Improve Security
https://blog.phylum.io/pick-a-python-lockfile-and-improve-security/ - PyPA specifications
https://packaging.python.org/en/latest/specifications/ - Creation of virtual environments
https://docs.python.org/3/library/venv.html - How to Use virtualenv in Python
https://learnpython.com/blog/how-to-use-virtualenv-python/ - Python Virtual Environments: A Primer
https://realpython.com/python-virtual-environments-a-primer/ - virtualenv Cheatsheet
https://aaronlelevier.github.io/virtualenv-cheatsheet/ - Installing Python Modules
https://docs.python.org/3/installing/index.html - Python: The Documentary | An origin story
https://www.youtube.com/watch?v=GfH4QL4VqJ0 - History of Python
https://en.wikipedia.org/wiki/History_of_Python - History of Python
https://www.geeksforgeeks.org/python/history-of-python/ - IPython: jedno z nejpropracovanějších interaktivních prostředí pro práci s Pythonem
https://www.root.cz/clanky/ipython-jedno-z-nejpropracova-nejsich-interaktivnich-prostredi-pro-praci-s-pythonem/ - Další kulaté výročí v IT: dvacet let existence Pythonu 2
https://www.root.cz/clanky/dalsi-kulate-vyroci-v-it-dvacet-let-existence-pythonu-2/ - PEP 684 – A Per-Interpreter GIL
https://peps.python.org/pep-0684/ - What Is the Python Global Interpreter Lock (GIL)?
https://realpython.com/python-gil/ - PEP 703 – Making the Global Interpreter Lock Optional in CPython
https://peps.python.org/pep-0703/ - GlobalInterpreterLock
https://wiki.python.org/moin/GlobalInterpreterLock - What is the Python Global Interpreter Lock (GIL)
https://www.geeksforgeeks.org/what-is-the-python-global-interpreter-lock-gil/ - Let's remove the Global Interpreter Lock
https://www.pypy.org/posts/2017/08/lets-remove-global-interpreter-lock-748023554216649595.html - Global interpreter lock
https://en.wikipedia.org/wiki/Global_interpreter_lock - Rychlost CPythonu 3.11 a 3.12 v porovnání s JIT a AOT překladači
https://www.root.cz/clanky/rychlost-cpythonu-3-11-a-3-12-v-porovnani-s-jit-a-aot-prekladaci-pythonu/ - Dokumentace Pythonu: balíček queue
https://docs.python.org/3/library/queue.html - Dokumentace Pythonu: balíček threading
https://docs.python.org/3/library/threading.html? - Dokumentace Pythonu: balíček multiprocessing
https://docs.python.org/3/library/multiprocessing.html - Dokumentace Pythonu: balíček asyncio
https://docs.python.org/3/library/asyncio.html - Synchronization Primitives
https://docs.python.org/3/library/asyncio-sync.html - Coroutines
https://docs.python.org/3/library/asyncio-task.html - Queues
https://docs.python.org/3/library/asyncio-queue.html - python-csp
https://python-csp.readthedocs.io/en/latest/ - TrellisSTM
http://peak.telecommunity.com/DevCenter/TrellisSTM - Python Multithreading and Multiprocessing Tutorial
https://www.toptal.com/python/beginners-guide-to-concurrency-and-parallelism-in-python - PEP 810: Explicit lazy imports
https://peps.python.org/pep-0810/ - PEP 814: Add frozendict built-in type
https://peps.python.org/pep-0814/ - PEP 661: Add sentinel built-in type
https://peps.python.org/pep-0661/ - PEP 798: Unpacking in comprehensions
https://peps.python.org/pep-0798/ - PEP 686: Python now uses UTF-8 as the default encoding
https://peps.python.org/pep-0686/ - PEP 829: Package startup configuration files
https://peps.python.org/pep-0829/ - Immutable (Python list of terms)
https://docs.python.org/3/glossary.html#term-immutable - builtins — Built-in objects
https://docs.python.org/3/library/builtins.html#module-builtins - Frozendict
https://docs.python.org/3/builtins/stdtypes.html#frozendict - Frozenset
https://docs.python.org/3/builtins/stdtypes.html#frozenset - PEP 744 – JIT Compilation
https://peps.python.org/pep-0744/ - Why is FrozenList different from tuple?
https://stackoverflow.com/questions/25676107/why-is-frozenlist-different-from-tuple - frozenlist 1.8.0 (PyPI)
https://pypi.org/project/frozenlist/ - frozenlist (GitHub)
https://github.com/aio-libs/frozenlist - Python's frozendict: The Immutable Dictionary
https://realpython.com/python315-frozendict/#freeze-an-existing-mapping - Comprehensions in Python – GeeksforGeeks
https://www.geeksforgeeks.org/python/comprehensions-in-python/ - PEP 728 – TypedDict with Typed Extra Items
https://peps.python.org/pep-0728/ - PEP 800 – Disjoint bases in the type system
https://peps.python.org/pep-0800/
