37. Kết hợp mẫu
37. Khớp mẫu
Khớp mẫu là hệ thống khớp cấu trúc của Python. Nó được thực hiện bởimatchtuyên bố vàcasekhoản.```python
match value:
case 0:
result = "zero"
case [x, y]:
result = x + y
case {"name": name}:
result = name
case _:
result = None
Ở cấp độ CPython, việc so khớp mẫu được biên dịch thành mã byte thông thường cộng với các hướng dẫn so khớp chuyên biệt. Trình thông dịch đánh giá chủ đề, thử từng trường hợp theo thứ tự, liên kết các tên để khớp thành công và chuyển đến nội dung đã chọn.
## 37.1`match`Tuyên bố
A`match`câu lệnh có một biểu thức chủ ngữ và một hoặc nhiều trường hợp.```python
match subject:
case pattern:
body
case pattern if guard:
body
case _:
body
```Biểu thức chủ đề được đánh giá một lần.```python
match compute():
case 1:
...
case 2:
...
compute()chạy một lần. Kết quả sau đó được kiểm tra đối với các trường hợp từ trên xuống dưới.
Về mặt khái niệm:```text subject = compute()
try case 1 if match succeeds: execute case 1 body else: try case 2
## 37.2 Mẫu và Biểu thức
Các mẫu trông giống như các biểu thức nhưng chúng tuân theo các quy tắc khác nhau.```python
match value:
case x:
...
```Điều này không so sánh`value`với một biến hiện có`x`. Nó bắt chủ đề vào một tên mới`x`.
Một mô hình chụp luôn thành công.```python
case x:
```có nghĩa:```text
bind x = subject
match succeeds
```Để so sánh với một hằng số được đặt tên, hãy sử dụng tên có dấu chấm:```python
case Color.RED:
```hoặc sử dụng một người bảo vệ:```python
case x if x == expected:
```Sự khác biệt này rất quan trọng vì việc khớp mẫu có cú pháp và quy tắc ràng buộc riêng.
## 37.3 Lệnh trường hợp
Các vụ án được xét xử theo thứ tự.```python
match value:
case int():
result = "integer"
case bool():
result = "boolean"
```Đây là một mệnh lệnh tồi vì`bool`là một lớp con của`int`.
```python
isinstance(True, int)
```là đúng.
Vì thế`True`trận đấu`int()`trước khi đạt được`bool()`.
Tốt hơn:```python
match value:
case bool():
result = "boolean"
case int():
result = "integer"
```Khớp mẫu sử dụng loại và cấu trúc thời gian chạy. Các trường hợp cụ thể hơn thường xuất hiện trước các trường hợp tổng quát hơn.
## 37.4 Mẫu ký tự đại diện
Mẫu ký tự đại diện`_`phù hợp với bất cứ điều gì và không ràng buộc gì.```python
match value:
case 0:
result = "zero"
case _:
result = "other"
```các`_`mẫu thường được sử dụng làm dự phòng cuối cùng.
Nó khác với tên chụp thông thường:```python
case name:
```Điều này ràng buộc`name`.
```python
case _:
```Điều này không ràng buộc`_`với tư cách là người địa phương mới cho kết quả trận đấu.
## 37.5 Mẫu chữ
Các mẫu chữ khớp với các giá trị như số, chuỗi, byte, boolean và`None`.
```python
match value:
case 0:
result = "zero"
case "ok":
result = "success"
case None:
result = "missing"
```Đối với hầu hết các nghĩa đen, việc so khớp sử dụng ngữ nghĩa bình đẳng.```text
subject == literal
```Đối với các hằng số đơn như`None`, `True`, Và`False`, việc so khớp sử dụng ngữ nghĩa đơn lẻ theo kiểu nhận dạng.
Các mẫu chữ rất hữu ích cho các thẻ, trạng thái nhỏ và đánh dấu giao thức.
## 37.6 Mẫu chụp
Một mẫu chụp liên kết một tên.```python
match value:
case x:
result = x
```Điều này luôn phù hợp.
Các mẫu chụp rất hữu ích bên trong các mẫu lớn hơn:```python
match point:
case [x, y]:
result = x + y
```Đây,`[x, y]`là một mẫu tuần tự. Những cái tên`x`Và`y`nắm bắt các yếu tố.
Sau khi khớp thành công, các tên bị ràng buộc sẽ có sẵn trong nội dung trường hợp.```python
match value:
case [x, y]:
print(x, y)
```Nếu khớp không thành công, các ràng buộc từ mẫu không thành công đó không được rò rỉ theo cách mà mã người dùng có thể dựa vào.
## 37.7 Mẫu giá trị
Mẫu giá trị so sánh chủ đề với giá trị được tham chiếu bằng tên có dấu chấm.```python
match color:
case Color.RED:
handle_red()
case Color.BLUE:
handle_blue()
```Tên có dấu chấm được đánh giá và so sánh với chủ đề.
Điều này khác với:```python
case RED:
```mà nắm bắt được một cái tên gọi là`RED`.
Đối với các hằng số, hãy sử dụng tên có dấu chấm, enum hoặc bộ bảo vệ.```python
class Status:
OK = "ok"
ERROR = "error"
match status:
case Status.OK:
...
```## 37.8 HOẶC Mẫu
Mẫu OR khớp nếu có bất kỳ mẫu thay thế nào khớp.```python
match value:
case 0 | 1 | 2:
result = "small"
```Tất cả các lựa chọn thay thế phải liên kết cùng một bộ tên.
Có hiệu lực:```python
match value:
case [x] | (x,):
result = x
```Về nguyên tắc không hợp lệ:```python
case [x] | [x, y]:
```bởi vì sự thay thế đầu tiên liên kết`x`, trong khi thứ hai liên kết`x`Và`y`.
Trình biên dịch kiểm tra tính nhất quán liên kết tên cho các mẫu OR.
## 37.9 NHƯ mẫu
Mẫu AS liên kết toàn bộ giá trị khớp trong khi cũng khớp với mẫu con.```python
match value:
case [x, y] as pair:
print(x, y, pair)
```Nếu chủ đề phù hợp`[x, y]`, sau đó:```text
x = first element
y = second element
pair = whole subject
```Điều này hữu ích khi bạn cần cả trường bị hủy cấu trúc và giá trị ban đầu.
## 37.10 Vệ binh
Người bảo vệ là một`if`điều kiện gắn liền với một trường hợp.```python
match value:
case [x, y] if x < y:
result = "ascending"
```Mẫu này được khớp đầu tiên. Nếu thành công, người bảo vệ sẽ được đánh giá.
Về mặt khái niệm:```text
if subject matches [x, y]:
if x < y:
execute body
else:
try next case
```Các vệ sĩ có thể chạy mã Python tùy ý. Họ có thể đưa ra các ngoại lệ, gọi hàm, thay đổi trạng thái hoặc phụ thuộc vào tên đã ghi.
Nếu người bảo vệ đánh giá là sai, trường hợp đó được coi là không được chọn và việc so khớp sẽ tiếp tục với trường hợp tiếp theo.
## 37.11 Mẫu trình tự
Mẫu trình tự khớp với các đối tượng giống trình tự.```python
match value:
case [x, y]:
result = x + y
```Điều này phù hợp với chuỗi có độ dài hai.
Ví dụ có thể phù hợp:```python
[1, 2]
(1, 2)
```Chuỗi và byte không được coi là chuỗi cho mục đích này, mặc dù chúng giống chuỗi trong các ngữ cảnh khác.
So khớp trình tự cần kiểm tra:```text
is the subject a sequence pattern candidate
does it have the required length
extract elements
match nested subpatterns
bind names
```## 37.12 Mẫu trình tự được gắn dấu sao
Mẫu được gắn dấu sao sẽ ghi lại phần giữa có độ dài thay đổi.```python
match value:
case [first, *middle, last]:
...
```Vì:```python
value = [1, 2, 3, 4]
```các ràng buộc là:```text
first = 1
middle = [2, 3]
last = 4
```Ảnh chụp được gắn dấu sao nhận được một danh sách.
Mẫu yêu cầu ít nhất đủ phần tử cho các vị trí không được gắn dấu sao.```python
case [first, *middle, last]:
```cần ít nhất hai phần tử.
## 37.13 Mẫu ánh xạ
Mẫu ánh xạ khớp với các đối tượng giống như ánh xạ.```python
match value:
case {"name": name, "age": age}:
...
```Điều này kiểm tra xem chủ đề có các khóa cần thiết hay không.
Vì:```python
value = {"name": "Ada", "age": 37, "city": "London"}
```mẫu khớp và liên kết:```text
name = "Ada"
age = 37
```Các khóa bổ sung được cho phép trừ khi mẫu sử dụng logic chặt chẽ hơn bên ngoài mẫu, chẳng hạn như bộ bảo vệ.
Các mẫu ánh xạ cũng có thể chụp các mục còn lại:```python
match value:
case {"name": name, **rest}:
...
```Sau đó`rest`nhận được một từ điển các khóa chưa khớp.
## 37.14 Mẫu lớp
Các mẫu lớp khớp với các đối tượng theo loại và thuộc tính.```python
match value:
case Point(x, y):
...
```Điều này kiểm tra xem`value`là một ví dụ của`Point`, sau đó trích xuất các trường.
Ý nghĩa của các trường vị trí được kiểm soát bởi`Point.__match_args__`.
Ví dụ:```python
class Point:
__match_args__ = ("x", "y")
def __init__(self, x, y):
self.x = x
self.y = y
```Sau đó:```python
match p:
case Point(x, y):
...
```về mặt khái niệm tương tự như:```text
isinstance(p, Point)
x = p.x
y = p.y
```với ngữ nghĩa khớp mẫu và hành vi lỗi.
## 37.15 Mẫu lớp từ khóa
Các mẫu lớp có thể đặt tên các thuộc tính một cách rõ ràng.```python
match value:
case Point(x=0, y=y):
...
```Điều này phù hợp với một`Point`của ai`x`thuộc tính phù hợp`0`, và ràng buộc`y`thuộc tính.
Các mẫu lớp từ khóa không phụ thuộc vào`__match_args__`cho những thuộc tính đó.
Về mặt khái niệm:```text
check isinstance(value, Point)
get value.x and match against 0
get value.y and bind y
```Tra cứu thuộc tính có thể thực thi mã, vì vậy các mẫu lớp có thể có tác dụng phụ nếu liên quan đến các thuộc tính hoặc quyền truy cập thuộc tính tùy chỉnh.
## 37,16`__match_args__`
`__match_args__`ánh xạ các trường mẫu lớp vị trí vào tên thuộc tính.```python
class Point:
__match_args__ = ("x", "y")
```Điều này cho phép:```python
case Point(a, b):
```có nghĩa là:```python
case Point(x=a, y=b):
```Đối với các lớp dữ liệu và các bộ dữ liệu được đặt tên, Python thường cung cấp các`__match_args__`tự động.
Nếu như`__match_args__`bị thiếu, trống hoặc không tương thích, các mẫu lớp vị trí có thể bị lỗi hoặc phát sinh lỗi tùy thuộc vào dạng mẫu.
## 37.17 Mẫu lồng nhau
Các mẫu có thể lồng nhau.```python
match value:
case {"point": Point(x, y), "label": label}:
...
```Điều này kiểm tra:```text
subject is a mapping
subject has key "point"
subject has key "label"
subject["point"] is a Point
extract Point.x and Point.y
bind label
```Các mẫu lồng nhau được biên dịch thành một chuỗi các hoạt động kiểm tra và trích xuất.
Nếu bất kỳ phần lồng nhau nào bị lỗi thì toàn bộ trường hợp sẽ không thành công và việc so khớp sẽ tiếp tục với trường hợp tiếp theo.
## 37.18 Ràng buộc tên
Tên bị ràng buộc trong trường hợp thành công sẽ trở thành các biến cục bộ trong phạm vi xung quanh.```python
def f(value):
match value:
case [x, y]:
return x + y
case _:
return 0
```Trình biên dịch xử lý`x`Và`y`như tên địa phương trong`f`.
Điều này có thể ảnh hưởng đến việc phân tích phạm vi. Tên được một mẫu ghi lại là một sự xuất hiện ràng buộc, tương tự như sự gán.
Ví dụ:```python
def f(value):
match value:
case x:
return x
```Đây,`x`là địa phương để`f`.
## 37.19 Liên kết khớp không thành công
Không nên sử dụng mẫu bị lỗi làm nguồn liên kết ổn định.
Ví dụ:```python
match value:
case [x, 0]:
...
case _:
...
```Nếu trường hợp đầu tiên không thành công sau khi liên kết một phần của cấu trúc, CPython phải tránh để lộ các liên kết một phần là kết quả thành công.
Ngữ nghĩa ngôn ngữ không cho phép bạn dựa vào tên bị ràng buộc trong các trận đấu thất bại.
Mã trình biên dịch và trình thông dịch phải tuân theo quy tắc này.
## 37.20 Mã byte khớp mẫu
So khớp mẫu sẽ biên dịch thành mã byte.
Một ví dụ đơn giản:```python
def f(value):
match value:
case [x, y]:
return x + y
case _:
return 0
```Cấu trúc mã byte khái niệm:```text
load subject
try sequence case:
check sequence
check length 2
unpack into x, y
execute body
return
fallback:
return 0
```CPython bao gồm các mã opcode dành riêng cho mẫu để kiểm tra thông thường, chẳng hạn như khớp trình tự, khớp ánh xạ, trích xuất khóa và khớp lớp. Tên và bố cục opcode chính xác có thể thay đổi giữa các phiên bản.
## 37.21 Sao chép chủ đề
Chủ đề thường phải có sẵn trong khi thử nhiều trường hợp.```python
match value:
case [x]:
...
case {"x": x}:
...
case _:
...
```Nếu trường hợp đầu tiên thất bại, trường hợp thứ hai vẫn cần chủ đề ban đầu.
Trình biên dịch phát ra các thao tác ngăn xếp để sao chép, bảo toàn hoặc loại bỏ chủ đề nếu cần.
Về mặt khái niệm:```text
subject on stack
try case 1
if fail, restore subject
try case 2
if fail, restore subject
fallback
```Kỷ luật ngăn xếp chính xác rất quan trọng vì việc khớp mẫu có nhiều đường dẫn lỗi.
## 37.22 Đường dẫn Thất bại
Một trường hợp có thể thất bại ở nhiều điểm:```text
wrong type
wrong sequence length
missing mapping key
class check fails
attribute extraction fails with AttributeError
nested subpattern fails
OR alternative fails
guard is false
```Một số lỗi là không khớp bình thường. Những người khác là ngoại lệ thực sự.
Việc so khớp mẫu phải phân biệt:```text
normal pattern failure
real runtime exception
```Ví dụ: khóa ánh xạ bị thiếu có nghĩa là mẫu ánh xạ không khớp.
Nhưng một người nhận tài sản làm tăng`RuntimeError`trong một mẫu lớp sẽ tuyên truyền ngoại lệ.
## 37.23 Bảo vệ và Ngoại lệ
Guard là mã Python thông thường.```python
match value:
case x if check(x):
...
```Nếu như`check(x)`tăng lên, ngoại lệ lan truyền. Trình thông dịch không coi đó là một kết quả khớp không thành công.
Về mặt khái niệm:```text
pattern succeeds
evaluate guard
returns true: select case
returns false: try next case
raises: propagate exception
```Điều này làm cho lính canh mạnh mẽ nhưng cũng hiệu quả.
## 37.24 Tra cứu khóa ánh xạ
Các mẫu ánh xạ sử dụng tra cứu khóa. Một mẫu như:```python
case {"name": name}:
```kiểm tra xem chủ đề có chứa khóa không`"name"`và rút ra giá trị của nó.
Việc triển khai phải tránh vô tình gọi ra hành vi làm thay đổi ngữ nghĩa so với các quy tắc mẫu ánh xạ.
Hành vi cấp nguồn quan trọng là:```text
required keys must exist
their values must match subpatterns
extra keys are allowed
```Nếu như`**rest`hiện diện, các cặp khóa-giá trị chưa khớp sẽ được sao chép vào từ điển mới.
## 37.25 Tra cứu thuộc tính mẫu lớp
Các mẫu lớp có thể thực hiện tra cứu thuộc tính.```python
case Point(x=x, y=y):
```Điều này có thể gọi:```text
Point-related descriptors
properties
__getattribute__
__getattr__
```Nếu quyền truy cập thuộc tính tăng lên`AttributeError`, mẫu lớp có thể bị lỗi do không khớp với thuộc tính đó. Các trường hợp ngoại lệ khác lan truyền.
Ví dụ:```python
class C:
@property
def x(self):
raise RuntimeError("bad")
match C():
case C(x=x):
...
```Điều này lan truyền`RuntimeError`.
## 37.26 Kết hợp mẫu và mô tả
Vì các mẫu lớp sử dụng quyền truy cập thuộc tính nên các bộ mô tả có thể tham gia.```python
class C:
@property
def x(self):
return 10
match C():
case C(x=10):
result = "matched"
```Trình lấy thuộc tính chạy trong quá trình khớp.
Điều này có nghĩa là việc khớp mẫu có thể kích hoạt mã người dùng. Nó không phải lúc nào cũng là một cuộc kiểm tra kết cấu thụ động.
## 37.27 So khớp mẫu và các lớp dữ liệu
Các lớp dữ liệu hoạt động tự nhiên với các mẫu lớp.```python
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
def f(p):
match p:
case Point(0, y):
return y
case Point(x, y):
return x + y
```Các lớp dữ liệu thường cung cấp`__match_args__`dựa trên các trường, do đó các mẫu lớp vị trí sẽ hoạt động.
Về mặt khái niệm:```text
Point(0, y)
matches Point instance
checks x == 0
binds y from p.y
```## 37.28 So khớp mẫu và Enum
Enums thường được sử dụng với các mẫu giá trị.```python
from enum import Enum
class TokenKind(Enum):
NAME = 1
NUMBER = 2
match kind:
case TokenKind.NAME:
...
case TokenKind.NUMBER:
...
```Các tên có dấu chấm là các mẫu giá trị nên chúng so sánh với các thành viên enum hiện có.
Đừng viết:```python
case NAME:
```trừ khi bạn có ý định nắm bắt một biến mới.
## 37.29 So khớp mẫu và AST
Đối sánh mẫu rất hữu ích cho các cấu trúc dạng cây.```python
match node:
case BinOp(left, "+", right):
...
case Literal(value):
...
```Trình biên dịch hoặc trình thông dịch có thể sử dụng các mẫu lớp để kiểm tra các loại nút.
Ví dụ:```python
@dataclass
class Literal:
value: object
@dataclass
class BinOp:
left: object
op: str
right: object
```Sau đó:```python
match node:
case BinOp(Literal(a), "+", Literal(b)):
return Literal(a + b)
```Điều này thể hiện sự phân hủy cấu trúc một cách trực tiếp.
## 37.30 So khớp mẫu và ngăn xếp mã byte
So khớp mẫu sử dụng ngăn xếp giá trị khung giống như các mã byte khác.
Chủ đề, giá trị được trích xuất trung gian, kết quả so sánh và giá trị dự phòng được bảo toàn có thể nằm trong ngăn xếp.
Một mẫu trình tự:```python
case [x, y]:
```về mặt khái niệm thì:```text
subject
check sequence
check length
unpack two elements
store x
store y
execute body
```Nếu thất bại, các giá trị tạm thời sẽ được bật lên và trường hợp tiếp theo bắt đầu từ hình dạng ngăn xếp sạch.
## 37.31 Trách nhiệm của trình biên dịch
Trình biên dịch phải tạo mã byte để bảo toàn một số bất biến:```text
subject evaluated once
cases tried in order
successful pattern bindings visible in body
failed pattern bindings not relied on
guards evaluated after binding
guards can access bound names
stack shape valid at every jump
exceptions propagate correctly
only first successful case runs
```Do đó, khớp mẫu vừa là tính năng ngôn ngữ vừa là tính năng trình biên dịch.
## 37.32 Trách nhiệm trong thời gian chạy
Khi chạy, CPython phải thực hiện:```text
type checks
sequence checks
mapping checks
class checks
attribute extraction
key extraction
equality checks
binding
guard evaluation
failure jumps
exception propagation
```Một số thao tác này là các thao tác chung của Python và có thể gọi mã người dùng.
Ví dụ:```python
case SomeClass(x=x):
```có thể thực thi logic mô tả cho`x`.
```python
case 10:
```có thể sử dụng so sánh bình đẳng.
Việc khớp mẫu phải chính xác theo mô hình đối tượng động của Python.
## 37.33 Khớp mẫu và bình đẳng
Các mẫu chữ và giá trị có thể sử dụng sự bình đẳng.```python
case 10:
```phù hợp nếu chủ đề bằng`10`.
Đối với các đối tượng do người dùng định nghĩa, đẳng thức có thể gọi`__eq__`.
```python
class C:
def __eq__(self, other):
print("compare")
return True
match C():
case 10:
print("matched")
```Điều này có thể thực thi mã người dùng.
Nếu đẳng thức tạo ra một ngoại lệ, ngoại lệ đó sẽ lan truyền.
## 37.34 Kết hợp mẫu và hiệu suất
Việc kết hợp mẫu có thể rõ ràng nhưng nó không phải là phép thuật. Nó vẫn thực hiện kiểm tra thời gian chạy.
Chi phí có thể bao gồm:```text
type checks
length checks
mapping lookups
attribute lookups
equality comparisons
temporary allocations
guard execution
bytecode branches
```Một cách đơn giản`if`chuỗi có thể nhanh hơn đối với các trường hợp vô hướng rất nhỏ.
Khớp mẫu hữu ích nhất khi cấu trúc có vấn đề:```text
nested data
AST nodes
protocol messages
token streams
configuration shapes
command parsing
event dispatch
```Sử dụng nó ở nơi nó cải thiện sự rõ ràng.
## 37.35 So khớp mẫu so với`if/elif`Cái này:```python
match value:
case 0:
...
case 1:
...
```có thể tương tự như:```python
if value == 0:
...
elif value == 1:
...
```Nhưng việc khớp mẫu còn đi xa hơn:```python
match value:
case {"type": "user", "name": name}:
...
case ["move", x, y]:
...
case Point(x=0, y=y):
...
```Nó kết hợp các bài kiểm tra kiểu, kiểm tra hình dạng, giải nén và ràng buộc.
## 37.36 So khớp mẫu và phân tích cấu trúc
Nhiệm vụ hủy cấu trúc yêu cầu hình dạng phải khớp hoặc tăng lên.```python
x, y = value
```Nếu như`value`không có chính xác hai mục, nó sẽ tăng lên.
Các bài kiểm tra khớp mẫu có hình dạng và có thể vượt qua.```python
match value:
case [x, y]:
...
case _:
...
```Không khớp`[x, y]`chỉ cần thử trường hợp tiếp theo.
Vì vậy, khớp mẫu là phá hủy có điều kiện.
## 37.37 Đối sánh mẫu và phạm vi
Tên được ghi lại trong các mẫu là các ràng buộc cục bộ.```python
def f(value):
match value:
case x:
return x
```Trình biên dịch xử lý`x`như địa phương để`f`.
Điều này có thể gây ngạc nhiên cho người dùng khi mong đợi sự so sánh với một biến bên ngoài.```python
expected = 10
def f(value):
match value:
case expected:
return True
```Điều này ghi lại thành một tên địa phương`expected`. Nó không so sánh với bên ngoài`expected`.
Sử dụng:```python
def f(value):
match value:
case x if x == expected:
return True
```hoặc sử dụng hằng số chấm.
## 37.38 Các trường hợp khớp mẫu và không thể truy cập
Một kiểu chụp nắm bắt mọi thứ.```python
match value:
case x:
...
case 0:
...
```Trường hợp thứ hai là không thể truy cập được.
Tương tự:```python
case _:
```vì trường hợp chưa phải là trường hợp cuối cùng khiến các trường hợp sau này không thể truy cập được.
Trình biên dịch phát hiện một số mẫu không thể bác bỏ ở các vị trí không hợp lệ.
Một mẫu không thể bác bỏ là một mẫu luôn phù hợp, chẳng hạn như:```text
_
x
object()
```trong nhiều bối cảnh.
## 37.39 Khớp mẫu và`object()`Một mẫu lớp không có đối số có thể khớp với bất kỳ phiên bản nào của lớp đó.```python
case object():
```Vì gần như tất cả các đối tượng bình thường đều là những thể hiện của`object`, điều này hoàn toàn phù hợp.
Nó khác với:```python
case object:
```đó là một mẫu chụp có tên`object`, trừ khi cú pháp được giải quyết khác nhau thông qua ngữ cảnh. Tránh đặt tên mơ hồ trong các mẫu.
## 37.40 Khớp mẫu và`None`Để phù hợp`None`, sử dụng:```python
case None:
```Đây là một mẫu đơn theo nghĩa đen.
Không sử dụng:```python
case x:
```và mong đợi nó so sánh với bên ngoài`x`.
Mẫu đơn cho`None`, `True`, Và`False`là phổ biến và rõ ràng.
## 37.41 So khớp mẫu và bảo mật
Khớp mẫu có thể thực thi mã người dùng.
Các điểm thực hiện tiềm năng bao gồm:```text
equality comparison
attribute access
descriptor access
mapping methods
sequence methods
guard expressions
```Đối với các đối tượng trong bộ nhớ đáng tin cậy, điều này là bình thường.
Đối với các đối tượng không đáng tin cậy có phương thức thù địch, việc khớp mẫu phải được xử lý giống như thực thi Python thông thường, không phải là truy vấn khai báo an toàn.
## 37.42 Kiểm tra việc khớp mẫu
sử dụng`dis`để kiểm tra mã byte phù hợp.```python
import dis
def f(value):
match value:
case [x, y]:
return x + y
case {"x": x}:
return x
case _:
return 0
dis.dis(f)
```Hãy tìm:```text
subject handling
pattern-specific checks
unpack operations
mapping operations
jumps between cases
stores for captured names
guard evaluation
return paths
```Mã byte chính xác thay đổi trên các phiên bản Python.
## 37.43 Công cụ so khớp mẫu tối thiểu
Một công cụ so khớp cấu trúc nhỏ cho danh sách có thể thể hiện ý tưởng.```python
def match_pair(value):
if isinstance(value, (list, tuple)) and len(value) == 2:
x, y = value
return True, {"x": x, "y": y}
return False, {}
```Sử dụng:```python
ok, binds = match_pair([1, 2])
if ok:
print(binds["x"] + binds["y"])
```Điều này phản ánh một phần nhỏ của:```python
match value:
case [x, y]:
print(x + y)
```CPython thực hiện điều này thông qua mã byte được biên dịch và trình trợ giúp thời gian chạy thay vì từ điển các ràng buộc.
## 37.44 Những hiểu lầm phổ biến
| Hiểu lầm | Đúng mẫu |
|---|---|
|`match`chỉ là một câu lệnh switch | Nó thực hiện khớp cấu trúc và liên kết |
|`case x`so sánh với biến`x`| Nó nắm bắt chủ đề vào`x` |
| `_`là chụp bình thường |`_`là ký tự đại diện trong mẫu |
| Chủ đề được đánh giá cho mọi trường hợp | Nó được đánh giá một lần |
| Việc khớp mẫu không có tác dụng phụ | Nó có thể gọi đẳng thức, bộ mô tả, bộ bảo vệ và móc thuộc tính |
| Trận đấu thất bại là ngoại lệ | Lỗi mẫu thông thường sẽ chuyển sang trường hợp tiếp theo |
| Các mẫu lớp kiểm tra các trường trực tiếp | Họ sử dụng quyền truy cập thuộc tính và`__match_args__`|
| Khớp mẫu luôn nhanh hơn`if`| Nó vẫn thực hiện kiểm tra thời gian chạy |
## 37,45 Chiến lược đọc
Bắt đầu với trường hợp vô hướng:```python
def f(x):
match x:
case 0:
return "zero"
case _:
return "other"
```Sau đó thêm cấu trúc:```python
def f(x):
match x:
case [a, b]:
return a + b
case {"name": name}:
return name
```Sau đó thêm các lớp:```python
class Point:
__match_args__ = ("x", "y")
def f(p):
match p:
case Point(0, y):
return y
case Point(x, y):
return x + y
```Đối với mỗi phiên bản:```python
import dis
dis.dis(f)
```Theo dõi:```text
where the subject is stored
where each case begins
which checks can fail normally
which operations can raise
where names are bound
where guards run
where fallback jumps go
```## 37.46 Tóm tắt chương
Khớp mẫu là hệ thống điều phối có điều kiện cấu trúc của CPython. Nó đánh giá một chủ đề một lần, thử các trường hợp theo thứ tự, kiểm tra các mẫu, liên kết tên, đánh giá các lính canh và thực thi phần thân phù hợp đầu tiên.
Mô hình cốt lõi là:
```văn bản
đánh giá chủ đề một lần
↓
thử mẫu trường hợp
↓
nếu mẫu không thành công: dọn dẹp và thử trường hợp tiếp theo
↓
nếu mẫu thành công: liên kết tên
↓
nếu bảo vệ tồn tại: đánh giá bảo vệ
↓
nếu bảo vệ đúng hoặc vắng mặt: thực thi phần thân