Lớp đối sánh Python

Cú pháp khớp mẫu được giới thiệu trong Python 3. 10 cho phép các kỹ thuật lập trình mới mạnh mẽ để ra quyết định trong ứng dụng

Lớp đối sánh Python
Bởi Serdar Yegulalp

Nhà văn cao cấp, InfoWorld.

Lớp đối sánh Python
hình ảnh robynmac / Getty

Mục lục

Cho xem nhiều hơn

Python, với tất cả sức mạnh và sự phổ biến của nó, từ lâu đã thiếu một dạng kiểm soát luồng có trong các ngôn ngữ khác—một cách để lấy một giá trị và khớp giá trị đó một cách tao nhã với một trong số các điều kiện có thể xảy ra. Trong C và C++, đó là cấu trúc switch/case; . ”

Các cách truyền thống để làm điều này trong Python không đẹp. Một là viết một chuỗi biểu thức if/elif/else. Cách khác là lưu trữ các giá trị để khớp dưới dạng các khóa trong từ điển, sau đó sử dụng các giá trị đó để thực hiện một hành động—e. g. , lưu trữ một hàm dưới dạng giá trị và sử dụng khóa hoặc một số biến khác làm đầu vào. Trong nhiều trường hợp, điều này hoạt động tốt, nhưng có thể cồng kềnh để xây dựng và bảo trì

[ Theo dõi các video hướng dẫn về Python thông minh của Serdar Yegulalp để tìm hiểu các thủ thuật Python thông minh trong 5 phút hoặc ít hơn ]

Sau khi nhiều đề xuất thêm một cú pháp giống như switch/case vào Python không thành công, một đề xuất gần đây của người sáng tạo ngôn ngữ Python, Guido van Rossum và một số cộng tác viên khác đã được chấp nhận cho Python 3. 10. kết hợp mô hình cấu trúc. Khớp mẫu cấu trúc không chỉ giúp thực hiện khớp kiểu switch/case đơn giản mà còn hỗ trợ phạm vi trường hợp sử dụng rộng hơn

Giới thiệu khớp mẫu cấu trúc Python

Khớp mẫu cấu trúc giới thiệu câu lệnh match/case và cú pháp mẫu cho Python. Tuyên bố match/case tuân theo cùng một phác thảo cơ bản như switch/case. Nó nhận một đối tượng, kiểm tra đối tượng dựa trên một hoặc nhiều mẫu khớp và thực hiện hành động nếu tìm thấy khớp

match command:
    case "quit":
        quit()
    case "reset":
        reset()
    case unknown_command:
        print (f"Unknown command '{unknown_command}')

Mỗi câu lệnh

from enum import Enum
class Command(Enum):
    QUIT = 0
    RESET = 1

match command:
    case Command.QUIT:
        quit()
    case Command.RESET:
        reset()
2 được theo sau bởi một mẫu để khớp với. Trong ví dụ trên, chúng tôi đang sử dụng các chuỗi đơn giản làm mục tiêu đối sánh của mình, nhưng có thể đối sánh phức tạp hơn

Python thực hiện so khớp bằng cách đi qua danh sách các trường hợp từ trên xuống dưới. Trong trận đấu đầu tiên, Python thực thi các câu lệnh trong khối

from enum import Enum
class Command(Enum):
    QUIT = 0
    RESET = 1

match command:
    case Command.QUIT:
        quit()
    case Command.RESET:
        reset()
2 tương ứng, sau đó bỏ qua đến cuối khối
from enum import Enum
class Command(Enum):
    QUIT = 0
    RESET = 1

match command:
    case Command.QUIT:
        quit()
    case Command.RESET:
        reset()
4 và tiếp tục với phần còn lại của chương trình. Không có "sự thất bại" giữa các trường hợp, nhưng có thể thiết kế logic của bạn để xử lý nhiều trường hợp có thể xảy ra trong một khối
from enum import Enum
class Command(Enum):
    QUIT = 0
    RESET = 1

match command:
    case Command.QUIT:
        quit()
    case Command.RESET:
        reset()
2. (Thêm về điều này sau. )

Cũng có thể chụp toàn bộ hoặc một phần trận đấu và sử dụng lại. Trong

from enum import Enum
class Command(Enum):
    QUIT = 0
    RESET = 1

match command:
    case Command.QUIT:
        quit()
    case Command.RESET:
        reset()
6 trong ví dụ của chúng tôi ở trên, giá trị được "bắt giữ" trong biến
from enum import Enum
class Command(Enum):
    QUIT = 0
    RESET = 1

match command:
    case Command.QUIT:
        quit()
    case Command.RESET:
        reset()
7 để chúng tôi có thể sử dụng lại nó

Khớp với các biến bằng khớp mẫu cấu trúc Python

Một lưu ý quan trọng đáng được đưa lên đây. Nếu bạn liệt kê các tên biến trong một câu lệnh

from enum import Enum
class Command(Enum):
    QUIT = 0
    RESET = 1

match command:
    case Command.QUIT:
        quit()
    case Command.RESET:
        reset()
2, điều đó không có nghĩa là phải so khớp nội dung của biến đã đặt tên. Các biến trong
from enum import Enum
class Command(Enum):
    QUIT = 0
    RESET = 1

match command:
    case Command.QUIT:
        quit()
    case Command.RESET:
        reset()
2 được sử dụng để nắm bắt giá trị đang được so khớp

Nếu bạn muốn khớp với nội dung của một biến, thì biến đó phải được thể hiện dưới dạng tên có dấu chấm, giống như một enum. Đây là một ví dụ

from enum import Enum
class Command(Enum):
    QUIT = 0
    RESET = 1

match command:
    case Command.QUIT:
        quit()
    case Command.RESET:
        reset()

Người ta không cần phải sử dụng enum; . Điều đó nói rằng, enums có xu hướng là cách quen thuộc và thành ngữ nhất để làm điều này trong Python

So khớp với nhiều phần tử bằng khớp mẫu cấu trúc Python

Chìa khóa để làm việc hiệu quả nhất với khớp mẫu không chỉ là sử dụng nó thay thế cho việc tra cứu từ điển. Đó là để mô tả cấu trúc của những gì bạn muốn khớp. Bằng cách này, bạn có thể thực hiện so khớp dựa trên số phần tử mà bạn đang so khớp hoặc sự kết hợp của chúng

Đây là một ví dụ phức tạp hơn một chút. Tại đây, người dùng nhập lệnh, tùy chọn theo sau là tên tệp

command = input()
match command.split():
    case ["quit"]:
        quit()
    case ["load", filename]:
        load_from(filename)
    case ["save", filename]:
        save_to(filename)
    case _:
        print (f"Command '{command}' not understood")

Hãy xem xét các trường hợp này theo thứ tự

  • command = input()
    match command.split():
        case ["quit"]:
            quit()
        case ["load", filename]:
            load_from(filename)
        case ["save", filename]:
            save_to(filename)
        case _:
            print (f"Command '{command}' not understood")
    
    0 kiểm tra xem những gì chúng ta đang đối mặt với
    from enum import Enum
    class Command(Enum):
        QUIT = 0
        RESET = 1
    
    match command:
        case Command.QUIT:
            quit()
        case Command.RESET:
            reset()
    
    4 có phải là một danh sách chỉ có mục
    command = input()
    match command.split():
        case ["quit"]:
            quit()
        case ["load", filename]:
            load_from(filename)
        case ["save", filename]:
            save_to(filename)
        case _:
            print (f"Command '{command}' not understood")
    
    2 hay không, xuất phát từ việc tách đầu vào
  • command = input()
    match command.split():
        case ["quit"]:
            quit()
        case ["load", filename]:
            load_from(filename)
        case ["save", filename]:
            save_to(filename)
        case _:
            print (f"Command '{command}' not understood")
    
    3 kiểm tra xem phần tử tách đầu tiên có phải là chuỗi
    command = input()
    match command.split():
        case ["quit"]:
            quit()
        case ["load", filename]:
            load_from(filename)
        case ["save", filename]:
            save_to(filename)
        case _:
            print (f"Command '{command}' not understood")
    
    4 không và nếu có chuỗi thứ hai theo sau. Nếu vậy, chúng tôi lưu trữ chuỗi thứ hai trong biến
    command = input()
    match command.split():
        case ["quit"]:
            quit()
        case ["load", filename]:
            load_from(filename)
        case ["save", filename]:
            save_to(filename)
        case _:
            print (f"Command '{command}' not understood")
    
    5 và sử dụng nó cho công việc tiếp theo. Tương tự cho
    command = input()
    match command.split():
        case ["quit"]:
            quit()
        case ["load", filename]:
            load_from(filename)
        case ["save", filename]:
            save_to(filename)
        case _:
            print (f"Command '{command}' not understood")
    
    6
  • command = input()
    match command.split():
        case ["quit"]:
            quit()
        case ["load", filename]:
            load_from(filename)
        case ["save", filename]:
            save_to(filename)
        case _:
            print (f"Command '{command}' not understood")
    
    7 là một trận đấu ký tự đại diện. Nó phù hợp nếu không có trận đấu nào khác được thực hiện cho đến thời điểm này. Lưu ý rằng biến gạch dưới, 
    command = input()
    match command.split():
        case ["quit"]:
            quit()
        case ["load", filename]:
            load_from(filename)
        case ["save", filename]:
            save_to(filename)
        case _:
            print (f"Command '{command}' not understood")
    
    8, không thực sự liên kết với bất kỳ thứ gì; . (Đó là lý do tại sao chúng tôi đề cập đến biến
    match media_object:
        case Image(type="jpg"):
            # Return as-is
            return media_object
        case Image(type="png") | Image(type="gif"):
            return render_as(media_object, "jpg")
        case Video():
            raise ValueError("Can't extract frames from video yet")
        case other_type:
            raise Exception(f"Media type {media_object} can't be handled yet")
    
    1 trong phần thân của khối
    from enum import Enum
    class Command(Enum):
        QUIT = 0
        RESET = 1
    
    match command:
        case Command.QUIT:
            quit()
        case Command.RESET:
            reset()
    
    2; không có gì được ghi lại. )

Các mẫu trong khớp mẫu cấu trúc Python

Các mẫu có thể là các giá trị đơn giản hoặc chúng có thể chứa logic khớp phức tạp hơn. Vài ví dụ

  • match media_object:
        case Image(type="jpg"):
            # Return as-is
            return media_object
        case Image(type="png") | Image(type="gif"):
            return render_as(media_object, "jpg")
        case Video():
            raise ValueError("Can't extract frames from video yet")
        case other_type:
            raise Exception(f"Media type {media_object} can't be handled yet")
    
    3. So khớp với giá trị duy nhất
    match media_object:
        case Image(type="jpg"):
            # Return as-is
            return media_object
        case Image(type="png") | Image(type="gif"):
            return render_as(media_object, "jpg")
        case Video():
            raise ValueError("Can't extract frames from video yet")
        case other_type:
            raise Exception(f"Media type {media_object} can't be handled yet")
    
    4
  • match media_object:
        case Image(type="jpg"):
            # Return as-is
            return media_object
        case Image(type="png") | Image(type="gif"):
            return render_as(media_object, "jpg")
        case Video():
            raise ValueError("Can't extract frames from video yet")
        case other_type:
            raise Exception(f"Media type {media_object} can't be handled yet")
    
    5. Phù hợp với bộ sưu tập
    match media_object:
        case Image(type="jpg"):
            # Return as-is
            return media_object
        case Image(type="png") | Image(type="gif"):
            return render_as(media_object, "jpg")
        case Video():
            raise ValueError("Can't extract frames from video yet")
        case other_type:
            raise Exception(f"Media type {media_object} can't be handled yet")
    
    6
  • match media_object:
        case Image(type="jpg"):
            # Return as-is
            return media_object
        case Image(type="png") | Image(type="gif"):
            return render_as(media_object, "jpg")
        case Video():
            raise ValueError("Can't extract frames from video yet")
        case other_type:
            raise Exception(f"Media type {media_object} can't be handled yet")
    
    7. So khớp với một bộ sưu tập có hai giá trị và đặt giá trị thứ hai vào biến chụp
    match media_object:
        case Image(type="jpg"):
            # Return as-is
            return media_object
        case Image(type="png") | Image(type="gif"):
            return render_as(media_object, "jpg")
        case Video():
            raise ValueError("Can't extract frames from video yet")
        case other_type:
            raise Exception(f"Media type {media_object} can't be handled yet")
    
    8
  • match media_object:
        case Image(type="jpg"):
            # Return as-is
            return media_object
        case Image(type="png") | Image(type="gif"):
            return render_as(media_object, "jpg")
        case Video():
            raise ValueError("Can't extract frames from video yet")
        case other_type:
            raise Exception(f"Media type {media_object} can't be handled yet")
    
    9. So khớp với bộ sưu tập có ít nhất một giá trị. Các giá trị khác, nếu có, được lưu trữ trong
    match media_object:
        case Image(type=media_type):
            print (f"Image of type {media_type}")
    0. Lưu ý rằng bạn chỉ có thể bao gồm một mục được gắn dấu sao cho mỗi bộ sưu tập (giống như đối số dấu sao trong hàm Python)
  • match media_object:
        case Image(type=media_type):
            print (f"Image of type {media_type}")
    1. Toán tử
    match media_object:
        case Image(type=media_type):
            print (f"Image of type {media_type}")
    2 (
    match media_object:
        case Image(type=media_type):
            print (f"Image of type {media_type}")
    3) có thể được sử dụng để cho phép xử lý nhiều trường hợp trong một khối
    from enum import Enum
    class Command(Enum):
        QUIT = 0
        RESET = 1
    
    match command:
        case Command.QUIT:
            quit()
        case Command.RESET:
            reset()
    
    2. Ở đây, chúng tôi so khớp với
    match media_object:
        case Image(type="jpg"):
            # Return as-is
            return media_object
        case Image(type="png") | Image(type="gif"):
            return render_as(media_object, "jpg")
        case Video():
            raise ValueError("Can't extract frames from video yet")
        case other_type:
            raise Exception(f"Media type {media_object} can't be handled yet")
    
    4,
    match media_object:
        case Image(type=media_type):
            print (f"Image of type {media_type}")
    6 hoặc
    match media_object:
        case Image(type=media_type):
            print (f"Image of type {media_type}")
    7
  • match media_object:
        case Image(type=media_type):
            print (f"Image of type {media_type}")
    8. Tương tự như trên, ngoại trừ bây giờ chúng tôi đặt mục phù hợp vào biến
    match media_object:
        case Image(type=media_type):
            print (f"Image of type {media_type}")
    9
  • switch/case0. Chỉ khớp với ảnh chụp nếu switch/case1 là đúng. Các biến chụp có thể được sử dụng trong biểu thức. Chẳng hạn, nếu chúng ta sử dụng switch/case2, thì ____1_______2 sẽ chỉ hợp lệ nếu giá trị thu được ___44_______4 thực tế nằm trong tập hợp ____44_______5
  • switch/case6. Mọi bộ sưu tập các mục bắt đầu bằng switch/case7 sẽ khớp với

Khớp với các đối tượng bằng khớp mẫu cấu trúc Python

Tính năng tiên tiến nhất của hệ thống khớp mẫu cấu trúc của Python là khả năng khớp với các đối tượng có thuộc tính cụ thể. Hãy xem xét một ứng dụng mà chúng tôi đang làm việc với một đối tượng có tên là switch/case8, mà chúng tôi muốn chuyển đổi thành tệp switch/case9 và trả về từ hàm

match media_object:
    case Image(type="jpg"):
        # Return as-is
        return media_object
    case Image(type="png") | Image(type="gif"):
        return render_as(media_object, "jpg")
    case Video():
        raise ValueError("Can't extract frames from video yet")
    case other_type:
        raise Exception(f"Media type {media_object} can't be handled yet")

Trong mỗi trường hợp trên, chúng tôi đang tìm kiếm một loại đối tượng cụ thể, đôi khi có các thuộc tính cụ thể. Trường hợp đầu tiên so khớp với đối tượng if/elif/else0 với thuộc tính if/elif/else1 được đặt thành if/elif/else2. Trường hợp thứ hai phù hợp nếu if/elif/else1 là if/elif/else4 hoặc if/elif/else5. Trường hợp thứ ba khớp với bất kỳ đối tượng nào thuộc loại if/elif/else6, bất kể thuộc tính của nó. Và trường hợp cuối cùng là tất cả của chúng tôi nếu mọi thứ khác không thành công

Bạn cũng có thể thực hiện chụp với đối tượng phù hợp

match media_object:
    case Image(type=media_type):
        print (f"Image of type {media_type}")

Sử dụng khớp mẫu cấu trúc Python hiệu quả

Chìa khóa với khớp mẫu cấu trúc Python là viết các kết quả phù hợp bao gồm các trường hợp cấu trúc mà bạn đang cố gắng so khớp. Các thử nghiệm đơn giản đối với các hằng số là tốt, nhưng nếu đó là tất cả những gì bạn đang làm, thì một tra cứu từ điển đơn giản có thể là một lựa chọn tốt hơn. Giá trị thực của việc so khớp mẫu cấu trúc là có thể so khớp với một mẫu đối tượng, không chỉ một đối tượng cụ thể hoặc thậm chí là một lựa chọn trong số chúng

[ Cũng trên InfoWorld. 8 dấu hiệu bạn đang làm Python đúng]

Một điều quan trọng khác cần ghi nhớ là thứ tự của các trận đấu. Những kết quả khớp nào bạn kiểm tra trước sẽ có tác động đến hiệu quả và độ chính xác của kết quả khớp của bạn nói chung. Hầu hết những người đã xây dựng chuỗi if/elif/else dài sẽ nhận ra điều này, nhưng khớp mẫu đòi hỏi bạn phải suy nghĩ về thứ tự cẩn thận hơn, do sự phức tạp tiềm ẩn. Đặt các kết quả khớp cụ thể nhất của bạn trước và các kết quả khớp chung nhất cuối cùng

Cuối cùng, nếu bạn gặp vấn đề có thể giải quyết bằng một chuỗi if/elif/else đơn giản hoặc tra từ điển — hãy sử dụng cách đó thay thế. Kết hợp mẫu là mạnh mẽ, nhưng không phổ biến. Sử dụng nó khi nó có ý nghĩa nhất cho một vấn đề

Có liên quan

  • con trăn
  • Ngôn ngữ lập trình
  • Phát triển phần mềm

Serdar Yegulalp là một nhà văn cao cấp tại InfoWorld, tập trung vào học máy, container hóa, devops, hệ sinh thái Python và đánh giá định kỳ

Khớp có nhanh hơn if other Python không?

Trăn 3. 10 câu lệnh so khớp nhanh hơn ở các chuỗi so khớp mẫu so với các câu lệnh if tương đương . Nhanh hơn nhiều. Các chức năng thứ hai chạy nhanh hơn 86% so với chức năng đầu tiên. Nguồn. github. com/tonybaloney/an…

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. Tuy nhiên, giờ đây, chúng ta có thể sử dụng câu lệnh so khớp . Điều này sẽ làm cho mã của bạn dễ đọc và dễ bảo trì hơn.

Python có câu lệnh đối sánh không?

Có, Python có chức năng Switch case . Câu lệnh đối sánh trường hợp cho phép người dùng triển khai chính xác các đoạn mã để chuyển đổi trường hợp. Nó có thể được sử dụng để truyền biến để so sánh và các câu lệnh trường hợp có thể được sử dụng để xác định các lệnh sẽ thực thi khi một trường hợp khớp.

Đối tượng đối sánh Python là gì?

Đối tượng khớp là đối tượng chứa thông tin về tìm kiếm và kết quả .