Khớp mẫu Python

Trong lịch sử, đã có hai tùy chọn hợp lý cho hành vi chuyển đổi Pythonic. sử dụng kiểm tra đẳng thức có điều kiện “nếu” (rõ ràng nhưng hơi xấu) hoặc tra cứu từ điển (sang trọng nhưng kém rõ ràng)

Cho đến bây giờ

Trăn 3. 10. 0a7 giới thiệu một chút cú pháp hay như một giải pháp thay thế. Chúng tôi đã có một thời gian trước khi nó được đưa vào sử dụng phổ biến, nhưng sự cứu trợ đang được tiến hành

Khớp mẫu cơ bản trên một chuỗi ký tự

Các công tắc cơ bản nhất phục vụ để thay thế cú pháp trên. Từ khóa “match” xác định phạm vi của công tắc với các câu lệnh “case” chỉ định từng giá trị có thể

Bàn giao "cái khác" với một trường hợp cơ sở

Python chỉ sử dụng dấu gạch dưới để xác định các phương thức ma thuật, để chỉ ra các thuộc tính của lớp riêng, để gán các biến giả và trả về hàm, cho các tên mangle… vì vậy nó cần thêm một dấu gạch dưới

Ký tự '_' được sử dụng trong cú pháp đối sánh mẫu dưới dạng ký tự đại diện nếu không tìm thấy đối sánh chính xác

Kết hợp mô hình cấu trúc nâng cao

Sức mạnh thực sự của khớp mẫu thường được tìm thấy nhiều hơn trong các ngôn ngữ chức năng (nghĩ OCaml, Haskell hoặc Miranda). Ngoài đối sánh theo nghĩa đen đã trình bày ở trên, đối sánh mẫu có thể được sử dụng để giải nén các đối tượng, đánh giá giá trị của các thuộc tính và gán các biến cho logic tiếp theo

Dưới đây, tôi đã viết một lớp Người đơn giản với hai thuộc tính. tên và tuổi. Tuổi là tùy chọn và có thể nhận giá trị Không có hoặc một số nguyên. Trình trang trí @dataclass cung cấp một chút đường cú pháp để đơn giản hóa logic, không cần __init__

Sử dụng cùng một cú pháp đối sánh trường hợp được trình bày ở trên, chúng ta có thể giải nén tên và tuổi của một cá thể Person

  1. Trong câu lệnh đầu tiên, chúng tôi khớp với bất kỳ tên nào, nhưng chúng tôi kiểm tra xem tuổi có phải là Không (tuổi=Không). Nếu vậy, chúng tôi không bao gồm tuổi trong phần giới thiệu của người đó
  2. Trong câu lệnh thứ hai, chúng tôi kiểm tra xem tuổi có trên 100 hay không với điều kiện nội tuyến (tuổi > 100)
  3. Và trong tuyên bố thứ ba, chúng tôi đề cập đến trường hợp chung nhất trong đó tuổi không phải là Không có và không lớn hơn một trăm

Logic giải nén này cực kỳ mạnh mẽ và cho phép lồng tùy ý. Chẳng hạn, người ta có thể giải nén một bộ đối tượng Người và khớp các mẫu nhiều Người

Bắt đầu với Python 3. 10

Nếu bạn cũng hào hứng như tôi và muốn tự mình kiểm tra cú pháp khớp mẫu mới của Python, hãy tải xuống. Chỉ cần lưu ý rằng sự phát triển vẫn không ổn định ở dạng alpha và bạn sẽ không sớm thấy việc áp dụng chính thống

Để lại nhận xét hoặc vỗ tay nếu bạn đã học được điều gì đó

Thêm nội dung bằng tiếng Anh. io. Đăng ký nhận bản tin hàng tuần miễn phí của chúng tôi. Nhận quyền truy cập độc quyền để viết các cơ hội và lời khuyên trong cộng đồng của chúng tôi Discord

Đây là một tính năng mới quan trọng trong Python 3. 10. Nó trông rất giống một câu lệnh chuyển đổi từ C, nhưng nó mạnh hơn rất nhiều. Nhiều ngôn ngữ hiện đại khác cũng có điều này, như Ruby. Nếu bạn có thể viết Python 3. 10 điều duy nhất, sau đó điều này có thể đơn giản hóa mã có rất nhiều kiểm tra của

a, (b, c) = (3, (4, 5))
4 và
a, (b, c) = (3, (4, 5))
5

13. 1. Kết quả khớp chính xác

Hãy xem xét một câu lệnh so khớp đơn giản trông giống như một câu lệnh chuyển đổi cổ điển trong ngôn ngữ C

item = 2

match item:
    case 1:
        print("One")
    case 2:
        print("Two")

Two

Thứ bạn đang đối sánh không được là một tên biến đơn giản (bạn sẽ thấy tại sao trong giây lát). Vì vậy, về cơ bản, đây là một câu lệnh chuyển đổi từ C, không có dự phòng. Trận đấu đầu tiên được chọn và nếu không có trận đấu nào phù hợp, bạn chỉ cần tiếp tục. (Nếu bạn muốn thất bại, có một hình thức tóm tắt tất cả mà bạn sẽ thấy sau)

13. 2. Giải nén bộ dữ liệu

Nhưng đây chỉ là bề nổi. Hãy bắt đầu mở rộng điều này để khớp cấu trúc bằng cách xem xét một nơi mà Python đã có khớp mẫu. bài tập. Điều này hoạt động và đã có trong nhiều năm (trên thực tế, Python 2 thậm chí còn hỗ trợ nó bên trong các định nghĩa hàm)

x, y = (1, 2)

a, (b, c) = (3, (4, 5))

Đây là cơ sở để so khớp mẫu - nó được mở rộng để bao gồm các ký tự và lớp, nhưng nó giống như thế này. Đây là những gì nó trông giống như

item = (1, 2)

match item:
    case (x, y, z):
        print(f"{x} {y} {z}")
    case (x, y):
        print(f"{x} {y}")
    case (x,):
        print(f"{x}")

1 2

Lưu ý rằng các tên biến đơn giản được gán, giống như ở bên trái của dấu bằng trong các ví dụ trước

Chúng ta cũng có thể kết hợp hai điều chúng ta đã thấy cho đến nay

________số 8

4

Bây giờ, điều này cố gắng “khớp” về mặt cấu trúc với từng trường hợp - khi một trường hợp được cho phép, nó sẽ được giải nén và bạn có thể sử dụng các giá trị đó (bạn cũng có thể sử dụng giá trị ban đầu). Nếu không có trường hợp nào phù hợp, bạn chỉ cần tiếp tục

Một chi tiết nhỏ - vì điều này đang cố khớp từng cái một, từ trên xuống dưới, nó không sử dụng phép lặp, mà là truy cập getitem. Vì vậy, một trình vòng lặp chung sẽ không hoạt động ở đây, giống như trong quá trình giải nén thông thường. Dù sao thì bạn cũng phải có một trình vòng lặp có thể khởi động lại, vì vậy đây không phải là vấn đề lớn, nhưng có thể hữu ích khi biết. Ngoài ra, các chuỗi không được bao gồm, mặc dù chúng có getitem, vì đó sẽ là một nguồn lỗi lớn -

a, (b, c) = (3, (4, 5))
6 không khớp với chuỗi dài 2

Một đối số

a, (b, c) = (3, (4, 5))
7 duy nhất cũng được hỗ trợ, giống như giải nén thông thường

a, (b, c) = (3, (4, 5))
2

a, (b, c) = (3, (4, 5))
3

13. 3. Các hình thức giải nén khác

Bạn có thể giải nén một số thứ khác. ký tự, lớp và một giá trị duy nhất - phải luôn xuất hiện sau cùng, vì nó khớp với mọi thứ. Tất cả những thứ này cũng có thể được lồng vào nhau một cách đệ quy

Two
0

Two
1

Có một vài quy tắc về việc đây là một ánh xạ thực tế. Đây là một kết hợp không đầy đủ - nếu có các cặp khóa/giá trị khác, bạn có thể lấy chúng bằng

a, (b, c) = (3, (4, 5))
8, nhưng bạn không cần phải thêm điều này để làm cho nó bỏ qua các giá trị bổ sung; . Bạn cũng cần chỉ định khóa

Các lớp phù hợp thông qua

a, (b, c) = (3, (4, 5))
5;

Two
2

Two
3

Các lớp tra cứu các thuộc tính nếu bạn đặt tên

Two
4

Two
5

Và nếu bạn có các đối số vị trí, thì có một thuộc tính

item = (1, 2)

match item:
    case (x, y, z):
        print(f"{x} {y} {z}")
    case (x, y):
        print(f"{x} {y}")
    case (x,):
        print(f"{x}")
0 ánh xạ các đối số vị trí thành các đối số từ khóa (và bạn nhận được điều này miễn phí nếu bạn sử dụng
item = (1, 2)

match item:
    case (x, y, z):
        print(f"{x} {y} {z}")
    case (x, y):
        print(f"{x} {y}")
    case (x,):
        print(f"{x}")
1. )

Two
6

Two
5

Two
8

Two
9

Các lớp tích hợp có một số xử lý tùy chỉnh ở đây, vì vậy những thứ như

item = (1, 2)

match item:
    case (x, y, z):
        print(f"{x} {y} {z}")
    case (x, y):
        print(f"{x} {y}")
    case (x,):
        print(f"{x}")
2 hoạt động như mong đợi - về cơ bản chúng trả về
item = (1, 2)

match item:
    case (x, y, z):
        print(f"{x} {y} {z}")
    case (x, y):
        print(f"{x} {y}")
    case (x,):
        print(f"{x}")
3. Nhưng các lớp tùy ý nhằm khớp với những gì chúng được xây dựng, thường không phải là chính chúng - bạn đã có điều đó. Bạn cũng có thể sử dụng
item = (1, 2)

match item:
    case (x, y, z):
        print(f"{x} {y} {z}")
    case (x, y):
        print(f"{x} {y}")
    case (x,):
        print(f"{x}")
4 nếu muốn

Nhiều trường hợp bạn có thể đã sử dụng

a, (b, c) = (3, (4, 5))
5 trước đây có thể được thay thế bằng khớp mẫu

Việc giải nén một giá trị sẽ khớp với bất kỳ thứ gì, vì vậy giá trị đó sẽ luôn xuất hiện sau cùng

x, y = (1, 2)
0

x, y = (1, 2)
1

Lưu ý rằng

item = (1, 2)

match item:
    case (x, y, z):
        print(f"{x} {y} {z}")
    case (x, y):
        print(f"{x} {y}")
    case (x,):
        print(f"{x}")
6 được xử lý hơi đặc biệt - nó được cho phép nhiều lần, không giống như giải nén thông thường

13. 4. Người bảo vệ

Bạn cũng có thể thiết lập các bảo vệ - nếu các câu lệnh được cho phép sau trận đấu, giống như trong phần hiểu. Hãy nhớ rằng, các trận đấu diễn ra từ trên xuống dưới, người đầu tiên thắng

x, y = (1, 2)
2

x, y = (1, 2)
3

Đáng buồn thay, các bộ bảo vệ vẫn không được phép thực hiện trên các vòng lặp thông thường để đảm bảo tính nhất quán với khả năng hiểu và giờ đây là các

item = (1, 2)

match item:
    case (x, y, z):
        print(f"{x} {y} {z}")
    case (x, y):
        print(f"{x} {y}")
    case (x,):
        print(f"{x}")
7 hoặc trên các câu lệnh tùy ý (như trong Ruby)

13. 5. Nhiều mẫu

Bạn có thể “hoặc” cùng nhiều mẫu

x, y = (1, 2)
4

x, y = (1, 2)
5

Điều này có thể hơi phức tạp vì bạn không biết mẫu nào hoặc mẫu nào khớp - thay vào đó hãy sử dụng câu lệnh nhiều trường hợp nếu điều đó quan trọng

13. 6. Một số ví dụ

Bây giờ bạn đã thấy cú pháp. Hãy xem xét một vài ví dụ

13. 6. 1. Ví dụ 1. chuỗi

Giả sử bạn muốn chọn hành vi dựa trên ký tự đầu tiên của chuỗi đầu vào. “*” theo sau không có gì khác cần bỏ qua, “+” cần bỏ qua và “-” cần đảo ngược

x, y = (1, 2)
6

x, y = (1, 2)
7

13. 6. 2. Ví dụ 2. Luồng so với. tên tệp

Giả sử bạn sẽ sử dụng

a, (b, c) = (3, (4, 5))
5 để gửi đi khác nhau dựa trên đầu vào iostream hoặc chuỗi

x, y = (1, 2)
8

x, y = (1, 2)
9

Lưu ý rằng điều này không hoàn toàn thanh lịch như nó có thể có được;

13. 6. 3. Ví dụ 3. Chọn thứ gì đó từ cấu trúc

Giả sử bạn có một số cấu trúc dữ liệu và bạn đang tìm kiếm thông tin có thể ở nhiều nơi khác nhau. Bạn có thể làm điều đó như thế này

a, (b, c) = (3, (4, 5))
0

a, (b, c) = (3, (4, 5))
1

13. 6. 4. Ví dụ 4. phân tích lệnh

Đây là một ví dụ chạy một số lệnh khác nhau, chẳng hạn như đối với một trò chơi

a, (b, c) = (3, (4, 5))
2

a, (b, c) = (3, (4, 5))
3

Lưu ý mức độ dễ đọc này vẫn còn, ngay cả đối với các lệnh phức tạp. Thực tế là bạn có thể lồng cái này làm cho nó rất mạnh để phân tích cú pháp

13. 7. Lời nhắc về các tính năng mới

Điều này không thể được viết với if, ifinstance được xâu chuỗi và lồng nhau và giải nén thủ công sao? . Nhưng giống như các tính năng mới khác, nó hạn chế hơn, giúp dễ đọc, dễ hiểu và suy luận hơn về. Nó chỉ định rằng bạn đang cố so khớp một biến duy nhất, trong khi các if bị xâu chuỗi có thể làm bất cứ điều gì, vì vậy người đọc phải kiểm tra từng if để xem liệu cùng một biến có đang được sử dụng hay không, v.v.

Python có khớp mẫu không?

'Structural Pattern Matching' mới được giới thiệu trong Python 3. 10 . Cú pháp cho tính năng mới này đã được đề xuất trong PEP 622 vào tháng 6 năm 2020. Câu lệnh khớp mẫu của Python được lấy cảm hứng từ cú pháp tương tự được tìm thấy trong Scala, Erlang và các ngôn ngữ khác.

Liệu Python 3. 9 có khớp không?

Trong Python 3. 9, bạn sẽ sử dụng câu lệnh if có bốn nhánh . Trước tiên, chúng tôi xác định, sau từ khóa khớp, biến mà chúng tôi muốn khớp. Sau đó, mỗi trường hợp bắt đầu bằng từ khóa trường hợp, theo sau là mẫu chúng tôi muốn kiểm tra.

Là Python 3. 10 hay?

Thông báo lỗi tốt hơn. Python thường được ca ngợi là ngôn ngữ lập trình thân thiện với người dùng. Mặc dù điều này đúng, nhưng có một số phần của Python có thể thân thiện hơn. Trăn 3. 10 đi kèm với một loạt thông báo lỗi chính xác và mang tính xây dựng hơn .

Đối sánh Python là gì?