Python 3.10 Changes#
New language features#
See Python 3.10: New features for more information about the changes in this section.
Parenthesized context managers#
You can now use enclosing parentheses for continuing lines across multiple lines in context managers:
# Python 3.9
with open('output.log', 'rw') as fout, open('input.csv') as fin:
fout.write(fin.read())
# Python 3.10
with (open('output.log', 'w') as fout, open('input.csv') as fin):
fout.write(fin.read())
# or
with (
CtxManager1() as example1,
CtxManager2() as example2,
CtxManager3() as example3,
):
See PEP 617: New PEG parser for CPython for more details.
Better error messages#
Python 3.10 emits more informative messages. For example, SyntaxError
exceptions for unclosed brackets now give the correct location and context of the error:
File "example.py", line 1
expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
^
SyntaxError: '{' was never closed
Structural pattern matching with match
and case
#
Python 3.10 introduces match
and case
statements that let you specify different actions to take, based on which pattern matches a given value:
match value:
case "hello":
print(value.upper())
case ("greeting", content):
print(f"Greeting is {content}")
case (label, content):
print(f"{label}: {content}")
case _:
print("bye")
If the wildcard, _
, is provided as the last case, it matches any value still not matched after evaluating previous cases. If the wildcard case is not supplied, the match
block is a null operation for unmatched values.
You can combine several literals in a single pattern using |
(“or”):
case (label, content) | {"label": label, "content": content}:
print(f"{label}: {content}")
See Python 3.10: Structural pattern matching for more information.
Type hints#
Use |
(pipe character) operator instead of Union
#
Python 3.10 lets you use the pipe character |
as a shortcut for Union
in type hints:
# Python 3.9
def func(num: Union[int, float]) -> Union[int, float]:
return num + 10
# Python 3.10
def func(num: int | float) -> int | float:
return num + 10
See Python 3.10: New type union operator for more details.
TypeAlias
#
Type aliases (TypeAlias
) have been added to the typing
module.
Type aliases are user-specified types which may be as complex as any type hint, and are specified with a simple variable assignment at the top level of a module.
Python 3.10 formalizes a way to explicitly declare an assignment as a type alias:
from typing import TypeAlias
StrCache: TypeAlias = 'Cache[str]' # a type alias
def func() -> StrCache:
...
User-defined type guards#
Type guards (TypeGuard
) have been added to the typing
module, allowing you to implement type narrowing with user-defined type guard functions.
To do this, use TypeGuard
to annotate the return value of a type guard function:
from typing import TypeGuard
def is_str_list(val: list[object]) -> TypeGuard[list[str]]:
'''Determines whether all objects in the list are strings'''
return all(isinstance(x, str) for x in val)
def func(val: list[object]):
if is_str_list(val):
# Type of ``val`` is narrowed to ``list[str]``.
print(" ".join(val))
else:
# Type of ``val`` remains as ``list[object]``.
print("Not a list of strings!")
The form def is_str_list(val: list[object]) -> TypeGuard[list[str]]: ...
means that if is_str_list(val)
returns True
, then val
narrows from list[object]
to list[str]
.
Type hints for callable objects#
Python 3.10 adds new options for creating type hints for callables:
Parameter specification variables forward the parameter types of one callable to another callable, expressing paramater type dependence.
Concatenate
is used in conjunction with parameter specification variables to annotate a higher order callable which adds or removes the parameters of another callable.
See Python 3.10: Parameter specification variables for more information.
Specifying text encoding#
When working with TextIOWrapper
and open
, Python uses the locale’s default encoding if no encoding is specified. This can can lead to bugs when working across platforms with conflicting default encodings. For example:
# May not work on Windows when non-ASCII characters in the file.
with open("README.md") as f:
long_description = f.read()
Python 3.10 gives you several ways to avoid creating this kind of bug:
Specify encodings explicitly. For example:
long_description = f.read(encoding="utf-8")
Use the
PYTHONWARNDEFAULTENCODING
environment variable (-X warn_default_encoding
from the command line) to emit anEncodingWarning
when the locale’s default encoding is being used.Where using the locale’s default encoding is the desired behaviour, pass
encoding="locale"
.
See Python documentation: Text encoding for more information.
Other language changes#
See Python 3.10: Other language changes for more information about the changes in this section.
The
int
type has a new method,int.bit_count
, returning the number of ones in the binary expansion of a given integer.Python 3.10 adds strict zipping (PEP 618: Strict zipping). The
zip
function now has an optionalstrict
flag which, whenTrue
, requires that the zipped iterables all have equal length and raises aValueError
if one iterable is exhausted before the others:for item in zip(range(3), ['fee', 'fi', 'fo', 'fum'], strict=True): print(item) ... (0, 'fee') (1, 'fi') (2, 'fo') Traceback (most recent call last): ... ValueError: zip() argument 2 is longer than argument 1
Two new builtins,
aiter
andanext
, have been added to provide asynchronous counterparts toiter
andnext
respectively.Static methods (
@staticmethod
) and class methods (@classmethod
) now inherit method attributes (__module__
,__name__
,__qualname__
,__doc__
,__annotations__
) and have a new__wrapped__
attribute.Additionally, static methods are now callable as regular functions:
class Trade(): @staticmethod def calculate_fee(trade_value): return trade_value * 0.001 reference = {1: calculate_fee} Trade.reference[1](2718281) # Python 3.9 -> # TypeError: 'staticmethod' object is not callable # Python 3.10 -> # 2718.281
See Python bug 43682 for more information.
For both
float
anddecimal.Decimal
types, hashes ofNaN
values now depend on object identity. Previously, bothfloat
andDecimal
NaN
values hashed to0
, causing hash collisions and resulting in poor runtime performance.In Python 3.9:
# Python 3.9 f1 = float("nan") f2 = float("nan") print(f1, f2) # nan nan print(f1 == f2) # False print(hash(f1)) # 0 print(hash(f2)) # 0 print(hash(f1) == hash(f2)) # True
In Python 3.10:
# Python 3.10 f1 = float("nan") f2 = float("nan") print(f1, f2) # nan nan print(f1 == f2) # False print(hash(f1)) # 305075651 print(hash(f2)) # 276643293 print(hash(f1) == hash(f2)) # False
See Python bug 87641 for more information.
Class and module objects now lazy-create empty annotations dicts on demand.
Previously, when trying to access the
__annotations__
attribute of a class, you might accidentally get the type hints dictionary from the base class instead of the derived class:class Base: a: int = 3 b: str = 'abc' class Derived(Base): pass print(Derived.__annotations__) # Python 3.9: annotations dict from `Base` # {'a': 'int', 'b': 'str'} # Python 3.10: lazily-created empty annotations dict # {}
See Python documentation: Annotations for more information.
object.__ipow__
falls back toobject.__pow__
andobject.__rpow__
if it returnsNotImplemented
.A new function,
mapping
, has been added todict
views such as those returned bydict.items
anddict.keys
to help with introspection. Themapping
function returns aMappingProxyType
.Builtin and extension functions that take integer arguments no longer accept
Decimal
,Fraction
or other objects that can only be converted to integers with a loss.Assignment expressions can now be used unparenthesized within set literals and set comprehensions, as well as in sequence indexes (but not slices). See Python bug 84811 for more information.
Functions have a new
__builtins__
attribute which is used to look for builtin symbols when a function is executed, instead of looking into__globals__['__builtins__']
.
Annotations#
When using
__future__.annotations
:Only annotations for simple names will take effect.
Annotations consisting of
yield
,yield from
,await
, or named expressions are now forbidden.Annotations consisting of unbound variables,
super
, and other expressions that might alter the processing of the symbol table have no effect.
Errors#
Deleting the
__debug__
constant now raises aSyntaxError
instead of aNameError
.SyntaxError
exceptions now haveend_lineno
andend_offset
attributes (set toNone
if not determined).
Optimizations#
See Python 3.10: Optimizations for more information about the changes in this section.
Constructors for
str
,bytes
, andbytearray
objects are now faster (around 30%-40% for small objects).The Python 3.10 interpreter gains 30%-40% improved performance from compilation with gcc’s
-fno-semantic-interposition
option. See Red Hat Enterprise Linux: Faster Python for more information.When using stringized annotations, annotations dicts for functions are no longer created when the function is created. Instead, they are stored in a compact form (tuple of strings), and the function object lazily converts this into the annotations dict on demand (when
func.__annotation__
is accessed).This optimization cuts the CPU time needed to define an annotated function by half.
Command startup with
runpy
, invoked viapython3 -m module-name
, is now on average 1.4x faster.Substring search functions such as
str1 in str2
andstr2.find(str1)
now sometimes use Crochemore & Perrin’s “Two-Way” string searching algorithm to avoid quadratic behavior on long strings. See [Python bug 86138][bug_86138] for more information.The
LOAD_ATTR
instruction now uses the new per-opcode caching mechanism. It is about 36% faster now for regular attributes and 44% faster for slots.New output buffer management code, along with the addition of the
readall
function to_compression.DecompressReader
, gives performance increases for compression and decompression:bz2 decompression: 1.09x ~ 1.17x faster
lzma decompression: 1.20x ~ 1.32x faster
zlib (gzip) decompression: 1.11x ~ 1.18x faster
In the SigTech framework,
zlib
is used inserde.py
andray.py
.Micro-optimizations to
_PyType_Lookup
improve type attribute cache lookup performance in the common case of cache hits. This makes the interpreter 1.04 times faster on average.The following built-in functions now support the faster PEP 590 vectorcall calling convention:
BZ2File
performance is improved by removing internalRLock
. This makes theBZ2File
thread unsafe in the face of multiple simultaneous readers or writers, like the equivalent classes ingzip
andlzma
.
Improved modules#
See Python 3.10: Improved modules for more information about the changes in this section.
collections.abc
#
In the collections.abc module,
collections.abc.Callable[[int, str], str]
will now have__args__
as(int, str, str)
instead of the previous([int, str], str)
.The
__args__
attribute of the parameterized generic forcollections.abc.Callable
now flattens type parameters similarly totyping.Callable
.A
TypeError
may be raised for invalid forms of parameterizingcollections.abc.Callable
, which may have passed silently in Python 3.9.
enum
#
In enum
, Enum.__repr__
now returns enum_name.member_name
and Enum.__str__
now returns member_name
.
Standard library enums available as module constants have a repr
of module_name.member_name
.
typing
#
For major changes to the typing
module, see Python 3.10: New features related to type hints.
In
typing.Literal
:Literal
now de-duplicates parameters.Equality comparisons between
Literal
objects are now order independent.Literal
comparisons now respect types. For example,Literal[0] == Literal[False]
previously evaluated toTrue
. It is nowFalse
. To support this change, the internally used type cache now supports differentiating types.Literal
objects will now raise aTypeError
exception during equality comparisons if any of their parameters are not hashable. Note that declaringLiteral
with unhashable parameters will not throw an error:from typing import Literal Literal[{0}] Literal[{0}] == Literal[{False}] # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: unhashable type: 'set'
A new function,
is_typeddict
, introspects whether an annotation is a [TypedDict
][pdoc_typeddict].Subclasses of
typing.Protocol
which only have data variables declared will now raise aTypeError
when checked withisinstance
unless they are decorated with theruntime_checkable
decorator.Previously, these checks passed silently. For runtime protocols, decorate subclasses with
runtime_checkable
.Importing from the
typing.io
andtyping.re
submodules will now emitDeprecationWarning
; anything belonging to those submodules should be imported directly fromtyping
instead.
See PEP 484: Type hints for more information.
Deprecations#
See Python 3.10: Deprecated for more information about the changes in this section.
A deprecation warning is raised if a numeric literal is immediately followed by one of these keywords:
and
else
for
if
in
is
or
For example, the code below is valid syntax prior to Python 3.10:
0in x 1or x 0if 1else 2 [0x1for x in y]
In future releases, the deprecation warning will be changed to a syntax warning and finally to a syntax error.
The entire
distutils
namespace is deprecated, to be removed in Python 3.12.Non-integer arguments to
random.randrange
are deprecated; theValueError
is deprecated in favor of aTypeError
.pathlib.Path.link_to
is deprecated and slated for removal in Python 3.12; usepathlib.Path.hardlink_to
instead.Certain deprecated
ssl
features are slated for removal in Python 3.11; see Python 3.10: Changes tossl
module.cgi.log
is deprecated and slated for removal in Python 3.12.
Threading deprecations#
The following
threading
methods are now deprecated and replaced:threading.currentThread
replaced bythreading.current_thread
threading.activeCount
replaced bythreading.active_count
threading.Condition.notifyAll
replaced bythreading.Condition.notify_all
threading.Event.isSet
replaced bythreading.Event.is_set
threading.Thread.setName
replaced bythreading.Thread.name
threading.thread.getName
replaced bythreading.Thread.name
threading.Thread.isDaemon
replaced bythreading.Thread.daemon
threading.Thread.setDaemon
replaced bythreading.Thread.daemon
The threading debug (
PYTHONTHREADDEBUG
environment variable) is deprecated in Python 3.10 and will be removed in Python 3.12.
Import syntax, import library, and import system deprecations#
Starting with Python 3.10, outdated import semantics will gradually start to raise
DeprecationWarning
orImportWarning
, including:find_loader
find_module
load_module
module_repr
__package__
__loader__
__cached__
Importing from the
typing.io
andtyping.re
submodules will now emitDeprecationWarning
. These submodules will be removed in a future version of Python. Anything belonging to these submodules should be imported directly fromtyping
instead.zimport.zipimporter.load_module
has been deprecated in preference forexec_module
.Deprecated
importlib
load_module
methods now raise aDeprecationWarning
; useexec_module
instead.Use of
importlib.abc.Loader.load_module
by the import system now triggers anImportWarning
, asexec_module
is preferred.The import system now triggers an
ImportWarning
when usingimportlib.abc.MetaPathFinder.find_module
andimportlib.abc.PathEntryFinder.find_module
, as the respective modules’find_spec
methods are preferred. To aid in porting, you can useimportlib.util.spec_from_loader
.The import system now triggers an
ImportWarning
when usingimportlib.abc.PathEntryFinder.find_loader
, as the preferred method isimportlib.abc.PathEntryFinder.find_spec
. To aid in porting, you can useimportlib.util.spec_from_loader
.importlib.abc.Finder
is deprecated (including its sole method,find_module
). Bothimportlib.abc.MetaPathFinder
andimportlib.abc.PathEntryFinder
no longer inherit from the class; users should inherit from one of these two classes as appropriate instead.importlib.abc.Loader.module_repr
,importlib.machinery.FrozenLoader.module_repr
, andimportlib.machinery.BuiltinLoader.module_repr
are deprecated and slated for removal in Python 3.12.Implementations of
importlib.abc.MetaPathFinder.find_module
will raise aDeprecationWarning
:importlib.abc.MetaPathFinder.find_module
importlib.abc.PathEntryFinder.find_loader
importlib.abc.PathEntryFinder.find_module
importlib.machinery.BuiltinImporter.find_module
importlib.machinery.FrozenImporter.find_module
importlib.machinery.PathFinder.find_module
importlib.machinery.WindowsRegistryFinder.find_module
importlib.machinery.FileFinder.find_loader
importlib.machinery.FileFinder.find_module
importlib.machinery.FileFinder.find_loader
These methods are slated for removal in Python 3.12.
The following deprecations are slated for removal in Python 3.12:
imp
importlib.find_loader
importlib.util.set_package_wrapper
importlib.util.set_loader_wrapper
importlib.util.module_for_loader
pkgutil.ImpImporter
pkgutil.ImpLoader
The import system now uses the
__spec__
attribute on modules before falling back onmodule_repr
for a module’s__repr__
method.
sqlite
deprecations#
Obsolete and undocumented
sqlite3.OptimizedUnicode
is now deprecated.sqlite3.enable_shared_cache
is now deprecated, scheduled for removal in Python 3.12. If a shared cache must be used, open the database in URI mode using thecache=shared
query parameter.
See the SQLite3 documentation for more details.
Removals#
See Python 3.10: Removed for more information about the changes in this section.
Removed deprecated aliases to Collections Abstract Base Classes from
collections
module.Removed parameter
loop
from most ofasyncio
’s high-level API; see Python 3.10: Optimizations.Removed the following special methods from
complex
class:complex.__divmod__
complex.__int__
complex.__float__
complex.__floordiv__
complex.__mod__
complex.__rdivmod__
complex.__rfloordiv__
complex.__rmod__
Removed
ParserBase.error
method from the private and undocumented_markupbase
module.Removed
unicodedata.ucnhash_CAPI
attribute; related private_PyUnicode_Name_CAPI
structure is moved to the internal C API.Removed deprecated
parser
module in favor of new PEG parser. Removed all C source and header files only used by the old parser, includingnode.h
,parser.h
,graminit.h
andgrammar.h
.Removed the following deprecated public C API functions:
PyParser_SimpleParseStringFlags
PyParser_SimpleParseStringFlagsFilename
PyParser_SimpleParseFileFlags
PyNode_Compile
Removed deprecated
formatter
module.Removed unnecessary function
PyModule_GetWarningsModule
.