In a similar way, errors involving unclosed string literals (single and triple quoted) now point to the start of the string instead of reporting EOF/EOL.
These improvements are inspired by previous work in the PyPy interpreter.
PEP 634: Structural Pattern Matching
¶
Structural pattern matching has been added in the form of a
match statement
and
case statements
of patterns with associated actions. Patterns consist of sequences, mappings, primitive data types as well as class instances. Pattern matching enables programs to extract information from complex data types, branch on the structure of data, and apply specific actions based on different forms of data.
Syntax and operations
¶
The generic syntax of pattern matching is:
match subject:
case <pattern_1>:
<action_1>
case <pattern_2>:
<action_2>
case <pattern_3>:
<action_3>
case _:
<action_wildcard>
A match statement takes an expression and compares its value to successive patterns given as one or more case blocks. Specifically, pattern matching operates by:
-
using data with type and shape (the
subject
)
-
evaluating the
subject
在
match
语句
-
comparing the subject with each pattern in a
case
statement from top to bottom until a match is confirmed.
-
executing the action associated with the pattern of the confirmed match
-
If an exact match is not confirmed, the last case, a wildcard
_
, if provided, will be used as the matching case. If an exact match is not confirmed and a wildcard case does not exist, the entire match block is a no-op.
Declarative approach
¶
Readers may be aware of pattern matching through the simple example of matching a subject (data object) to a literal (pattern) with the switch statement found in C, Java or JavaScript (and many other languages). Often the switch statement is used for comparison of an object/expression with case statements containing literals.
More powerful examples of pattern matching can be found in languages such as Scala and Elixir. With structural pattern matching, the approach is “declarative” and explicitly states the conditions (the patterns) for data to match.
While an “imperative” series of instructions using nested “if” statements could be used to accomplish something similar to structural pattern matching, it is less clear than the “declarative” approach. Instead the “declarative” approach states the conditions to meet for a match and is more readable through its explicit patterns. While structural pattern matching can be used in its simplest form comparing a variable to a literal in a case statement, its true value for Python lies in its handling of the subject’s type and shape.
Simple pattern: match to a literal
¶
Let’s look at this example as pattern matching in its simplest form: a value, the subject, being matched to several literals, the patterns. In the example below,
status
is the subject of the match statement. The patterns are each of the case statements, where literals represent request status codes. The associated action to the case is executed after a match:
def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Something's wrong with the internet"
If the above function is passed a
status
of 418, “I’m a teapot” is returned. If the above function is passed a
status
of 500, the case statement with
_
will match as a wildcard, and “Something’s wrong with the internet” is returned. Note the last block: the variable name,
_
, acts as a
wildcard
and insures the subject will always match. The use of
_
is optional.
You can combine several literals in a single pattern using
|
(“or”):
case 401 | 403 | 404:
return "Not allowed"
Behavior without the wildcard
¶
If we modify the above example by removing the last case block, the example becomes:
def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
Without the use of
_
in a case statement, a match may not exist. If no match exists, the behavior is a no-op. For example, if
status
of 500 is passed, a no-op occurs.
Patterns with a literal and variable
¶
Patterns can look like unpacking assignments, and a pattern may be used to bind variables. In this example, a data point can be unpacked to its x-coordinate and y-coordinate:
# point is an (x, y) tuple
match point:
case (0, 0):
print("Origin")
case (0, y):
print(f"Y={y}")
case (x, 0):
print(f"X={x}")
case (x, y):
print(f"X={x}, Y={y}")
case _:
raise ValueError("Not a point")
The first pattern has two literals,
(0, 0)
, and may be thought of as an extension of the literal pattern shown above. The next two patterns combine a literal and a variable, and the variable
binds
a value from the subject (
point
). The fourth pattern captures two values, which makes it conceptually similar to the unpacking assignment
(x, y) = point
.
Patterns and classes
¶
If you are using classes to structure your data, you can use as a pattern the class name followed by an argument list resembling a constructor. This pattern has the ability to capture class attributes into variables:
class Point:
x: int
y: int
def location(point):
match point:
case Point(x=0, y=0):
print("Origin is the point's location.")
case Point(x=0, y=y):
print(f"Y={y} and the point is on the y-axis.")
case Point(x=x, y=0):
print(f"X={x} and the point is on the x-axis.")
case Point():
print("The point is located somewhere else on the plane.")
case _:
print("Not a point")
Patterns with positional parameters
¶
You can use positional parameters with some builtin classes that provide an ordering for their attributes (e.g. dataclasses). You can also define a specific position for attributes in patterns by setting the
__match_args__
special attribute in your classes. If it’s set to (“x”, “y”), the following patterns are all equivalent (and all bind the
y
属性到
var
variable):
Point(1, var)
Point(1, y=var)
Point(x=1, y=var)
Point(y=var, x=1)
Nested patterns
¶
Patterns can be arbitrarily nested. For example, if our data is a short list of points, it could be matched like this:
match points:
case []:
print("No points in the list.")
case [Point(0, 0)]:
print("The origin is the only point in the list.")
case [Point(x, y)]:
print(f"A single point {x}, {y} is in the list.")
case [Point(0, y1), Point(0, y2)]:
print(f"Two points on the Y axis at {y1}, {y2} are in the list.")
case _:
print("Something else is found in the list.")
Complex patterns and the wildcard
¶
To this point, the examples have used
_
alone in the last case statement. A wildcard can be used in more complex patterns, such as
('error', code, _)
。例如:
match test_variable:
case ('warning', code, 40):
print("A warning has been received.")
case ('error', code, _):
print(f"An error {code} occurred.")
In the above case,
test_variable
will match for (‘error’, code, 100) and (‘error’, code, 800).
Guard
¶
We can add an
if
clause to a pattern, known as a “guard”. If the guard is false,
match
goes on to try the next case block. Note that value capture happens before the guard is evaluated:
match point:
case Point(x, y) if x == y:
print(f"The point is located on the diagonal Y=X at {x}.")
case Point(x, y):
print(f"Point is not on the diagonal.")
Other Key Features
¶
Several other key features:
-
Like unpacking assignments, tuple and list patterns have exactly the same meaning and actually match arbitrary sequences. Technically, the subject must be a sequence. Therefore, an important exception is that patterns don’t match iterators. Also, to prevent a common mistake, sequence patterns don’t match strings.
-
Sequence patterns support wildcards:
[x, y, *rest]
and
(x, y,
*rest)
work similar to wildcards in unpacking assignments. The name after
*
还可以为
_
,所以
(x, y, *_)
matches a sequence of at least two items without binding the remaining items.
-
Mapping patterns:
{"bandwidth": b, "latency": l}
captures the
"bandwidth"
and
"latency"
values from a dict. Unlike sequence patterns, extra keys are ignored. A wildcard
**rest
is also supported. (But
**_
would be redundant, so is not allowed.)
-
Subpatterns may be captured using the
as
关键词:
case (Point(x1, y1), Point(x2, y2) as p2): ...
This binds x1, y1, x2, y2 like you would expect without the
as
clause, and p2 to the entire second item of the subject.
-
Most literals are compared by equality. However, the singletons
True
,
False
and
None
are compared by identity.
-
Named constants may be used in patterns. These named constants must be dotted names to prevent the constant from being interpreted as a capture variable:
from enum import Enum
class Color(Enum):
RED = 0
GREEN = 1
BLUE = 2
color = Color.GREEN
match color:
case Color.RED:
print("I see red!")
case Color.GREEN:
print("Grass is green")
case Color.BLUE:
print("I'm feeling the blues :(")
For the full specification see
PEP 634
. Motivation and rationale are in
PEP 635
, and a longer tutorial is in
PEP 636
.
改进模块
¶
asyncio
¶
Add missing
connect_accepted_socket()
method. (Contributed by Alex Grönholm in
bpo-41332
)。
argparse
¶
Misleading phrase “optional arguments” was replaced with “options” in argparse help. Some tests might require adaptation if they rely on exact output match. (Contributed by Raymond Hettinger in
bpo-9694
)。
array
¶
The
index()
方法为
array.array
now has optional
start
and
stop
parameters. (Contributed by Anders Lorentsen and Zackery Spytz in
bpo-31956
)。
asynchat, asyncore, smtpd
¶
These modules have been marked as deprecated in their module documentation since Python 3.6. An import-time
DeprecationWarning
has now been added to all three of these modules.
bdb
¶
添加
clearBreakpoints()
to reset all set breakpoints. (Contributed by Irit Katriel in
bpo-24160
)。
bisect
¶
Added the possibility of providing a
key
function to the APIs in the
bisect
module. (Contributed by Raymond Hettinger in
bpo-4356
)。
contextlib
¶
添加
contextlib.aclosing()
context manager to safely close async generators and objects representing asynchronously released resources. (Contributed by Joongi Kim and John Belmonte in
bpo-41229
)。
Add asynchronous context manager support to
contextlib.nullcontext()
. (Contributed by Tom Gringauz in
bpo-41543
)。
添加
AsyncContextDecorator
, for supporting usage of async context managers as decorators.
dataclasses
¶
Keyword-only fields
¶
dataclasses now supports fields that are keyword-only in the generated __init__ method. There are a number of ways of specifying keyword-only fields.
You can say that every field is keyword-only:
from dataclasses import dataclass
@dataclass(kw_only=True)
class Birthday:
name: str
birthday: datetime.date
Both
name
and
birthday
are keyword-only parameters to the generated __init__ method.
You can specify keyword-only on a per-field basis:
from dataclasses import dataclass, field
@dataclass
class Birthday:
name: str
birthday: datetime.date = field(kw_only=True)
Here only
birthday
is keyword-only. If you set
kw_only
on individual fields, be aware that there are rules about re-ordering fields due to keyword-only fields needing to follow non-keyword-only fields. See the full dataclasses documentation for details.
You can also specify that all fields following a KW_ONLY marker are keyword-only. This will probably be the most common usage:
from dataclasses import dataclass, KW_ONLY
@dataclass
class Point:
x: float
y: float
_: KW_ONLY
z: float = 0.0
t: float = 0.0
这里,
z
and
t
are keyword-only parameters, while
x
and
y
are not. (Contributed by Eric V. Smith in
bpo-43532
)。
distutils
¶
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
, and most other commonly used APIs are available elsewhere in the standard library (such as
platform
,
shutil
,
subprocess
or
sysconfig
). There are no plans to migrate any other functionality from
distutils
, and applications that are using other functions should plan to make private copies of the code. Refer to
PEP 632
for discussion.
The
bdist_wininst
command deprecated in Python 3.8 has been removed. The
bdist_wheel
command is now recommended to distribute binary packages on Windows. (Contributed by Victor Stinner in
bpo-42802
)。
doctest
¶
When a module does not define
__loader__
, fall back to
__spec__.loader
. (Contributed by Brett Cannon in
bpo-42133
)。
encodings
¶
encodings.normalize_encoding()
now ignores non-ASCII characters. (Contributed by Hai Shi in
bpo-39337
)。
enum
¶
Enum
__repr__()
now returns
enum_name.member_name
and
__str__()
now returns
member_name
. Stdlib enums available as module constants have a
repr()
of
module_name.member_name
. (Contributed by Ethan Furman in
bpo-40066
)。
添加
enum.StrEnum
for enums where all members are strings. (Contributed by Ethan Furman in
bpo-41816
)。
faulthandler
¶
The
faulthandler
module now detects if a fatal error occurs during a garbage collector collection. (Contributed by Victor Stinner in
bpo-44466
)。
glob
¶
添加
root_dir
and
dir_fd
parameters in
glob()
and
iglob()
which allow to specify the root directory for searching. (Contributed by Serhiy Storchaka in
bpo-38144
)。
hashlib
¶
The hashlib module requires OpenSSL 1.1.1 or newer. (Contributed by Christian Heimes in
PEP 644
and
bpo-43669
)。
The hashlib module has preliminary support for OpenSSL 3.0.0. (Contributed by Christian Heimes in
bpo-38820
and other issues.)
The pure-Python fallback of
pbkdf2_hmac()
is deprecated. In the future PBKDF2-HMAC will only be available when Python has been built with OpenSSL support. (Contributed by Christian Heimes in
bpo-43880
)。
hmac
¶
The hmac module now uses OpenSSL’s HMAC implementation internally. (Contributed by Christian Heimes in
bpo-40645
)。
IDLE and idlelib
¶
Make IDLE invoke
sys.excepthook()
(when started without ‘-n’). User hooks were previously ignored. (Contributed by Ken Hilton in
bpo-43008
)。
Rearrange the settings dialog. Split the General tab into Windows and Shell/Ed tabs. Move help sources, which extend the Help menu, to the Extensions tab. Make space for new options and shorten the dialog. The latter makes the dialog better fit small screens. (Contributed by Terry Jan Reedy in
bpo-40468
.) Move the indent space setting from the Font tab to the new Windows tab. (Contributed by Mark Roseman and Terry Jan Reedy in
bpo-33962
)。
The changes above were backported to a 3.9 maintenance release.
Add a Shell sidebar. Move the primary prompt (‘>>>’) to the sidebar. Add secondary prompts (’…’) to the sidebar. Left click and optional drag selects one or more lines of text, as with the editor line number sidebar. Right click after selecting text lines displays a context menu with ‘copy with prompts’. This zips together prompts from the sidebar with lines from the selected text. This option also appears on the context menu for the text. (Contributed by Tal Einat in
bpo-37903
)。
Use spaces instead of tabs to indent interactive code. This makes interactive code entries ‘look right’. Making this feasible was a major motivation for adding the shell sidebar. (Contributed by Terry Jan Reedy in
bpo-37892
)。
Highlight the new
soft keywords
match
,
case
,和
_
in pattern-matching statements. However, this highlighting is not perfect and will be incorrect in some rare cases, including some
_
-s in
case
patterns. (Contributed by Tal Einat in
bpo-44010
)。
New in 3.10 maintenance releases.
Apply syntax highlighting to
.pyi
files. (Contributed by Alex Waygood and Terry Jan Reedy in
bpo-45447
)。
Include prompts when saving Shell with inputs and outputs. (Contributed by Terry Jan Reedy in
gh-95191
)。
linecache
¶
When a module does not define
__loader__
, fall back to
__spec__.loader
. (Contributed by Brett Cannon in
bpo-42133
)。
os
¶
添加
os.cpu_count()
support for VxWorks RTOS. (Contributed by Peixing Xin in
bpo-41440
)。
Add a new function
os.eventfd()
and related helpers to wrap the
eventfd2
syscall on Linux. (Contributed by Christian Heimes in
bpo-41001
)。
添加
os.splice()
that allows to move data between two file descriptors without copying between kernel address space and user address space, where one of the file descriptors must refer to a pipe. (Contributed by Pablo Galindo in
bpo-41625
)。
添加
O_EVTONLY
,
O_FSYNC
,
O_SYMLINK
and
O_NOFOLLOW_ANY
for macOS. (Contributed by Donghee Na in
bpo-43106
)。
os.path
¶
os.path.realpath()
现在接受
strict
keyword-only argument. When set to
True
,
OSError
is raised if a path doesn’t exist or a symlink loop is encountered. (Contributed by Barney Gale in
bpo-43757
)。
py_compile
¶
添加
--quiet
option to command-line interface of
py_compile
. (Contributed by Gregory Schevchenko in
bpo-38731
)。
site
¶
When a module does not define
__loader__
, fall back to
__spec__.loader
. (Contributed by Brett Cannon in
bpo-42133
)。
socket
¶
The exception
socket.timeout
现在是别名化的
TimeoutError
. (Contributed by Christian Heimes in
bpo-42413
)。
Add option to create MPTCP sockets with
IPPROTO_MPTCP
(Contributed by Rui Cunha in
bpo-43571
)。
添加
IP_RECVTOS
option to receive the type of service (ToS) or DSCP/ECN fields (Contributed by Georg Sauthoff in
bpo-44077
)。
ssl
¶
The ssl module requires OpenSSL 1.1.1 or newer. (Contributed by Christian Heimes in
PEP 644
and
bpo-43669
)。
The ssl module has preliminary support for OpenSSL 3.0.0 and new option
OP_IGNORE_UNEXPECTED_EOF
. (Contributed by Christian Heimes in
bpo-38820
,
bpo-43794
,
bpo-43788
,
bpo-43791
,
bpo-43799
,
bpo-43920
,
bpo-43789
,和
bpo-43811
)。
Deprecated function and use of deprecated constants now result in a
DeprecationWarning
.
ssl.SSLContext.options
has
OP_NO_SSLv2
and
OP_NO_SSLv3
set by default and therefore cannot warn about setting the flag again. The
deprecation section
has a list of deprecated features. (Contributed by Christian Heimes in
bpo-43880
)。
The ssl module now has more secure default settings. Ciphers without forward secrecy or SHA-1 MAC are disabled by default. Security level 2 prohibits weak RSA, DH, and ECC keys with less than 112 bits of security.
SSLContext
defaults to minimum protocol version TLS 1.2. Settings are based on Hynek Schlawack’s research. (Contributed by Christian Heimes in
bpo-43998
)。
The deprecated protocols SSL 3.0, TLS 1.0, and TLS 1.1 are no longer officially supported. Python does not block them actively. However OpenSSL build options, distro configurations, vendor patches, and cipher suites may prevent a successful handshake.
添加
timeout
参数用于
ssl.get_server_certificate()
function. (Contributed by Zackery Spytz in
bpo-31870
)。
The ssl module uses heap-types and multi-phase initialization. (Contributed by Christian Heimes in
bpo-42333
)。
A new verify flag
VERIFY_X509_PARTIAL_CHAIN
has been added. (Contributed by l0x in
bpo-40849
)。
sys
¶
添加
sys.orig_argv
attribute: the list of the original command line arguments passed to the Python executable. (Contributed by Victor Stinner in
bpo-23427
)。
添加
sys.stdlib_module_names
, containing the list of the standard library module names. (Contributed by Victor Stinner in
bpo-42955
)。
typing
¶
For major changes, see
New Features Related to Type Hints
.
行为在
typing.Literal
was changed to conform with
PEP 586
and to match the behavior of static type checkers specified in the PEP.
-
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 to
True
. It is now
False
. To support this change, the internally used type cache now supports differentiating types.
-
Literal
objects will now raise a
TypeError
exception during equality comparisons if any of their parameters are not
hashable
. Note that declaring
Literal
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'
(Contributed by Yurii Karabas in
bpo-42345
)。
Add new function
typing.is_typeddict()
to introspect if an annotation is a
typing.TypedDict
. (Contributed by Patrick Reader in
bpo-41792
)。
子类化的
typing.Protocol
which only have data variables declared will now raise a
TypeError
when checked with
isinstance
unless they are decorated with
runtime_checkable()
. Previously, these checks passed silently. Users should decorate their subclasses with the
runtime_checkable()
decorator if they want runtime protocols. (Contributed by Yurii Karabas in
bpo-38908
)。
Importing from the
typing.io
and
typing.re
submodules will now emit
DeprecationWarning
. These submodules have been deprecated since Python 3.8 and will be removed in a future version of Python. Anything belonging to those submodules should be imported directly from
typing
instead. (Contributed by Sebastian Rittau in
bpo-38291
)。
urllib.parse
¶
Python versions earlier than Python 3.10 allowed using both
;
and
&
as query parameter separators in
urllib.parse.parse_qs()
and
urllib.parse.parse_qsl()
. Due to security concerns, and to conform with newer W3C recommendations, this has been changed to allow only a single separator key, with
&
as the default. This change also affects
cgi.parse()
and
cgi.parse_multipart()
as they use the affected functions internally. For more details, please see their respective documentation. (Contributed by Adam Goldschmidt, Senthil Kumaran and Ken Jin in
bpo-42967
)。
The presence of newline or tab characters in parts of a URL allows for some forms of attacks. Following the WHATWG specification that updates
RFC 3986
, ASCII newline
\n
,
\r
and tab
\t
characters are stripped from the URL by the parser in
urllib.parse
preventing such attacks. The removal characters are controlled by a new module level variable
urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE
。(见
gh-88048
)