Version of the Python 3.10 , work on which began May 25, 2020, is scheduled for release October 4, 2021 and will contain a number of interesting innovations. One of the most promising innovations will be structured pattern matching (structured pattern matching). For this, a special pattern matching instruction will be introduced match
. The pattern matching functionality will undoubtedly be of interest, especially to FP programmers, where it plays an important role. The rest of the novelties of the new version of the language are described here .
Python, for all its power and popularity, for a long time did not have the form of flow control found in other languages - a way to take a value and elegantly match it to one of many possible conditions. In the C and C ++ languages, this is done by a construct switch/case
; in Rust and F #, this construct is called pattern matching.
The traditional ways of doing this in Python are not elegant. One of them is to write a chain of expressions if/elif/else
. Another is in storing values that are matched as keys in a dictionary, and then using the values by key to perform an action - for example, storing a function as a value and using a key or some other variable as input. In many cases, these techniques work well, but are cumbersome to design and maintain.
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()