Strukturierter Mustervergleich in Python 3.10

Die Version von Python 3.10 , an der am 25. Mai 2020 begonnen wurde, soll am 4. Oktober 2021 veröffentlicht werden und eine Reihe interessanter Neuerungen enthalten. Eine der vielversprechendsten Innovationen wird der strukturierte Mustervergleich (strukturierter Mustervergleich) sein. Hierzu wird eine spezielle Mustervergleichsanweisung eingeführt match



. Die Pattern Matching-Funktionalität wird zweifellos von Interesse sein, insbesondere für FP-Programmierer, wo sie eine wichtige Rolle spielt. Der Rest der Neuheiten der neuen Version der Sprache wird hier beschrieben .





Python hatte trotz all seiner Leistungsfähigkeit und Popularität lange Zeit nicht die Form der Flusskontrolle, die in anderen Sprachen zu finden war - eine Möglichkeit, einen Wert zu nehmen und ihn elegant einer von vielen möglichen Bedingungen zuzuordnen. In den Sprachen C und C ++ erfolgt dies durch ein Konstrukt switch/case



. In Rust und F # wird dieses Konstrukt als Mustervergleich bezeichnet.





Die traditionellen Methoden in Python sind nicht elegant. Eine davon ist, eine Kette von Ausdrücken zu schreiben if/elif/else



. Eine andere Möglichkeit besteht darin, Werte zu speichern, die als Schlüssel in einem Wörterbuch übereinstimmen, und dann die Werte nach Schlüssel zu verwenden, um eine Aktion auszuführen - beispielsweise eine Funktion als Wert zu speichern und einen Schlüssel oder eine andere Variable als Eingabe zu verwenden. In vielen Fällen funktionieren diese Techniken gut, sind jedoch umständlich zu entwerfen und zu warten.





Python , switch/case



, Python 3.10 Python : . switch/case



, .









  • Python





























Python

Python match/case



. match/case



, switch/case



. , , .





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



case



, . .





Python , . Python case



, match



. case



«», case



( ).





. case



, unknown_command



, «» unknown_command, .





. case



, , . case



, .





, , . :





from enum import Enum

class Command(Enum):
    QUIT = 0
    RESET = 1

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



; . , , , Python.





, , , , . , , , .





. , .





command = input()

match command.split():
    case [""]:
        quit()
    case ["", filename]:
        load_from(filename)
    case ["", filename]:
        save_to(filename)
    case _:
        print (f"  '{command}'")
      
      



case



:





case [""]:



, , ""



, .





case ["", filename]:



, ""



, . , filename



. case ["", filename]:



.





case _:



. , . , _



; _



match



, () ( command



case



; .)





, . :





case "a":



"a"



.





case ["a","b"]:



["a","b"]



.





case ["a", value1]:



, value1



.





case ["a", *values]:



, , . , , . , ( Python).





case ("a"|"b"|"c"):



(|



) , case



case



. "a"



, "b"



, "c"



.





case ("a"|"b"|"c") as letter:



, , letter



.





case ["a", value] if <>:



, . . , if



valid_values



, case



, .





case ["z", _]:



, "z"



.





Python , . , media_object



.jpg .





match media_object:
    case Image(type="jpg"):
        #   
        return media_object
    case Image(type="png") | Image(type="gif"):
        return render_as(media_object, "jpg")
    case Video():
        raise ValueError("     ")
    case other_type:
        raise Exception(f"  {media_object}  ")
      
      



case



, . case



Image



, "jpg"



. case



, "png"



"gif"



. case



, Video



, . case



, .





:





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



Python , , . , , , . , .





, . , , . , if/elif/else



, , - . , - .





, if/elif/else



— ! , . , .





:





  • switch/case





# : 
#       
#  Python  3.10.

#   switch/case
def match_errno(errno):
    match errno:
        case 0:
            pass
        case 1:
            pass
        case 42:
            print("42!")
        case _:    #    
            print(" ")
      
      







#     
def command_split(command):
    match command.split():
        case ["make"]:
            print("make  ")
        case ["make", cmd]:
            print(f"  make: {cmd}")
        case ["restart"]:
            print(" ")
        case ["rm", *files]:
            print(f" : {files}")
        case _:
            print("  ")
      
      



  • (|)





#         (|)
def match_alternatives(command):
    match command.split():
        case [""] | [" ", ""]:
            print("   ")
        case ["", obj] | ["", " ", obj] | ["", obj, " "]:
            print(f" : {obj}")
      
      



  • as





#         as
def match_capture_subpattern(command):
    match command.split():
        case [" ", ("" | "" | "" | "") as direction]:
            print(f"   {direction}")
      
      



  • if





#        if
def match_guard(command, exits):
    match command.split():
        case [" ", direction] if direction in exits:
            print(f"   {direction}")
        case [" ", _]:
            print(f"     ")
      
      







#   
from dataclasses import dataclass

@dataclass
class Click:
    position: tuple[int, int]
    button: str

@dataclass
class KeyPress:
    key_name: str

@dataclass
class Quit:
    pass

def match_by_class(event):
    match event:
        case Click(position=(x,y), button="left"):
            print(f"    {x,y}")
        case Click(position=(x,y)):
            print(f"    {x,y}")
        case KeyPress("Q"|"q") | Quit():
            print("  ")
        case KeyPress(key_name="up arrow"):
            print(" ")
        case KeyPress():
            pass #    
        case other_event:
            raise ValueError(f' : {other_event}')
      
      







#   
def match_json_event(event):
    match event:
        case {"transport": "http"}:
            print(" insecure  ")
        case {"verb": "GET", "page": "articles", "pageno": n}:
            print(f"     {n}...")
        case {"verb": "POST", "page": "signup"}:
            print("   ")
      
      



:





def main():
    # x, y = 1, 2
    command_split("make")
    command_split("make clean")
    command_split("restart")
    command_split("rm a b c")
    command_split("doesnt match")
    match_errno(42)
    match_alternatives("go north")
    match_alternatives("pick up sword")
    match_capture_subpattern("go north")
    match_capture_subpattern("go east")
    match_guard("go north", exits=["east", "south"])
    match_guard("go north", exits=["north"])
    match_by_class(Click(position=(0,0), button="left"))
    match_by_class(Quit())

    try:
        match_by_class("BADVALUE")
    except ValueError:
        pass

    match_json_event({"verb": "GET", "page": "articles", "pageno": 5, "info": "extra"})
    pass

if name == 'main':     
    main()
      
      



. . Github , . «» . . , - .








All Articles