4.10.2021 Opreliz Python 3.10 released.
Among other updates it was possible to use the SWITCH-CASE
structure, which is called a structural content of templates or Pattern Matching
How to use this design?
The question is created in order to have information about Pattern Matching
in Russian. This issue is not disclosed relative to Python 3.10 on RUSO
Answer 1, Authority 100%
in Python 3.10 Pattern Matching appeared
This material – the translation of the article “How to Use Structural Pattern Matching in Python “
In the new Python 3.10 release, the Case / Match
operators, which are responsible for implementing the Syntax language Pattern-Matching .
python, despite its simplicity and popularity, unlike other languages, did not have a separate flow control unit of Flow Control) – the method to take a value and elegantly compare it with one of the many possible Conditions. In C and C++, this feature is implemented by the switch / case
design, and in Rust it is called Pattern Matching .
Elegant ways to implement it in Python, except to use the if / elif / else
design and search by dictionary, before that moment did not exist. Both ways work, but because of their cumbersome, they could make it difficult for the readability of the code.
In recent years, several attempts have been made to enable Switch / Case
type syntax in Python, but they all have failed. This is the first implementation of the structural pattern matching (Structural Pattern Matching), which is now available only in the software version.
Introduction to Pattern Matching on Python
Structural pattern matching (Structural Pattern Matching) Enters the Match / Case
statement, which works on the same scheme as Switch / Case
. The operator checks the object for compliance with one or several templates and, if the coincidence is found, performs action.
Match Command:
Case "Quit":
quit ()
Case "Reset":
reset ()
Case Unknown_Command:
Print (F "Unknown Command '{Unknown_Command}'")
Behind each expression Case
follows a pattern for comparison. In this example, the top-down rows with the operator goes down, and if such a mapping is found, the operator is executed. You can also capture all or part of the coincidence and reuse them. In our example, in the case of a pattern of unknown_command
, we used it again inside F-lines .
Mapping Variables using Pattern Matching
If you want to compare the value with constants, then the constants should be attributed to the fields of the class:
class commander:
Quit = 0.
RESET = 1.
Command = 0.
Match Command:
Case Command.Quit:
quit ()
Case Command.reset:
reset ()
If you try to do this without resorting to classes, for example, so:
quit = 0
RESET = 1.
Command = 0.
Match Command:
Case Quit:
quit ()
Case Reset:
reset ()
Get an error in response related to the fact that the name does not apply to the well-known pattern:
Name Capture ‘Quit’ Makes Remaining Patterns Unreachable
Mapping multiple items using Pattern Matching
Pattern Matching is used not only as a dictionary search for a dictionary. It is used to describe the structure of what you want to compare. Thus, you can compare based on the number of compared items or combinations thereof.
Here is a more complex example. Here the user enters the command for which the file name is followed:
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")
Let’s look at Case options in order:
case ['quit']:
checks whether that we match the list only with thequit '
element obtained after separating the entered data usingSplit ()
.Case ['Load', FileName]:
Checks whether the first divided element isLoad '
, and whether the second string should be followed. If the second line is, the second line is saved in thefilename
variable and is used for further work. Similarly, it is checkedCase ["Save", FileName]:
.Case _:
This is a coincidence with a wildcard (Wildcard Match) . There is a coincidence, if no other coincidence happened before that moment. Note that the bottom underscore (_
) is not tied to anything, in this case the lower underscore is used as a command of theMATCH
command, that the case under consideration is a substitution sign (Wildcard) . (That is why we refer to the variable command in the body of thecase
block, because nothing was captured.)
Templates in Structural Pattern Matching
Templates can be simple values or contain a more complex matching logic.
Here are some examples:
Case 'A':
match with the only'A'
.Case ['A', 'B']:
match with the collection['a', 'b']
.Case ['A', Value1]:
match with a collection in which two values and place the second value in theValue1
variable.Case ['A', * Values]:
match the collection in which at least one value. The remaining values if they are, store invalues
. Note that you can enable only one element with an asterisk in the template.Case ('A' | 'B' | 'c'):
Operatoror
, it is|
, can be used for processing Multiple calls in one CASE block. Here we compare'a'
,'b'
, orc '
.Case ('A' | 'B' | 'C') as letter:
The same as above, except that we now place the corresponding item in theletter variable
.Case ['A', Value] if ...:
The variable is associated only if expression is true. The variables that we want to connect can be used in...
. For example, if we useif value in valid_values
, thencase
will be valid only if the captured value of Value was actually in thecollection of Valid_Values
.Case ['z', _]:
There will be any collection of elements that starts withZ '
.
Mapping with objects using Pattern Matching
The most advanced function Pattern Matchin G in Python is the ability to match objects with specific properties. Consider the application in which we work with the object Media_Object
. We want to convert this object to the .jpg
file and return from the function.
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")
In each of the Case
described above, we are looking for an object of a certain type, sometimes with certain attributes. In the first case, we are looking for the conformity of the image
object, which type
is attributed as 'jpg'
. In the second case
there is a comparison if Type matches the 'png'
or 'gif'
. In the third Case
there is a check on the conformity of the object Type Video
, while the attribute does not matter. And in the latter case, we get everything that was not selected earlier.
You can also capture objects with comparison of objects:
Match media_object:
Case Image (Type = Media_Type):
Print (F "Image of Type {media_type}")
Effective use of Pattern Matching
The key point when working with Match / Case
in Python lies in writing patterns in which the structure of what you want to work with. Simple tests for constants are good, but if all that you do, it is better to just make a search by the dictionary. The real value of structural mapping with the template (Structural Pattern Matching) in Python is the ability to match the object template, and not just with some one object or even with their set.
Another important detail that should be borne in mind is the procedure for writing comparisons. What comparisons you check first will affect the effectiveness and accuracy of your comparison as a whole. Place the most specific comparisons in the first place, and the most common ones on the last.
Ultimately, if you have a problem that can be solved using if / elif / else
or search by the dictionary, then use them instead of Match / Case
. Pattern Matching is a powerful, but not a versatile solution. Use it when it is most appropriate.
Read more with Pattern Matching documentation in Python (PEP 622) You can find here .