2020年5月25日に開始されたPython3.10のバージョンは、2021年10月4日のリリースが予定されており、多くの興味深いイノベーションが含まれています。最も有望なイノベーションの1つは、構造化パターンマッチング(構造化パターンマッチング)です。このために、特別なパターンマッチング命令 が導入されmatch
ます。パターンマッチング機能は、特にFPプログラマーにとって、間違いなく興味深いものであり、重要な役割を果たします。新しいバージョンの言語のその他の新規性については、ここで説明します。
Pythonは、そのすべての能力と人気のために、長い間、他の言語で見られるフロー制御の形式を持っていませんでした-値を取得し、それを多くの可能な条件の1つにエレガントにマッピングする方法。CおよびC ++言語では、これは構成によって行われswitch/case
ます。RustとF#では、この構成はパターンマッチングと呼ばれます。
Pythonでこれを行う従来の方法は、エレガントではありません。それらの1つは、式のチェーンを作成することですif/elif/else
。もう1つは、キーとして一致する値を辞書に保存し、キーごとに値を使用してアクションを実行することです。たとえば、関数を値として保存し、キーまたはその他の変数を入力として使用します。多くの場合、これらの手法はうまく機能しますが、設計と保守が面倒です。
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()