From ff13658e4ab3cf70a592b27a8a9562847f12f624 Mon Sep 17 00:00:00 2001 From: SAM <8dmasters@gmail.com> Date: Tue, 4 Jun 2024 01:07:24 +0530 Subject: [PATCH 01/11] Create match_case_statement.md --- contrib/advanced-python/match_case_statement.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 contrib/advanced-python/match_case_statement.md diff --git a/contrib/advanced-python/match_case_statement.md b/contrib/advanced-python/match_case_statement.md new file mode 100644 index 0000000..e69de29 From 3ac978f6a97fa53d1a111d3fb0132984a13ce6de Mon Sep 17 00:00:00 2001 From: SAM <8dmasters@gmail.com> Date: Tue, 4 Jun 2024 01:07:36 +0530 Subject: [PATCH 02/11] Update index.md Added match_case_statement index --- contrib/advanced-python/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/advanced-python/index.md b/contrib/advanced-python/index.md index b31544e..c262aaa 100644 --- a/contrib/advanced-python/index.md +++ b/contrib/advanced-python/index.md @@ -10,3 +10,4 @@ - [Protocols](protocols.md) - [Exception Handling in Python](exception-handling.md) - [Generators](generators.md) +- [Match Case Statement](match_case_statement.md) \ No newline at end of file From a2f8b49b1e77b1d4d9fcc376509e401955b468b7 Mon Sep 17 00:00:00 2001 From: SAM <60264918+SAM-DEV007@users.noreply.github.com> Date: Tue, 4 Jun 2024 15:47:49 +0530 Subject: [PATCH 03/11] Update match_case_statement.md Added introduction and syntax --- .../advanced-python/match_case_statement.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/contrib/advanced-python/match_case_statement.md b/contrib/advanced-python/match_case_statement.md index e69de29..d4ad861 100644 --- a/contrib/advanced-python/match_case_statement.md +++ b/contrib/advanced-python/match_case_statement.md @@ -0,0 +1,22 @@ +# Match Case Statements +## Introduction +Match and case statements are introduced in Python 3.10 for structural pattern matching of patterns with associated actions. It offers more readible and +cleaniness to the code as opposed to the traditional `if-else` statements. They also have destructuring, pattern matching and checks for specific properties in +addition to the traditional `switch-case` statements in other languages, which makes them more versatile. + +## Syntax +``` +match : + case : + + case : + + case _: + +``` +A match statement takes a statement which compares it to the various cases and their patterns. If any of the pattern is matched successively, the task is performed accordingly. If an exact match is not confirmed, the last case, a wildcard `_`, if provided, will be used as the matching case. + +## Pattern Matching +As discussed earlier, match case statements use pattern matching where the patterns consist of sequences, mappings, primitive data types as well as class instances. The structural pattern matching uses declarative approach and it nexplicitly states the conditions for the patterns to match with the data. + +### Patterns with a Literal From 55717a47dee55e6d62aa161e52840b7075dc0689 Mon Sep 17 00:00:00 2001 From: SAM <60264918+SAM-DEV007@users.noreply.github.com> Date: Tue, 4 Jun 2024 16:48:03 +0530 Subject: [PATCH 04/11] Update match_case_statement.md Added patterns with a literal section --- .../advanced-python/match_case_statement.md | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/contrib/advanced-python/match_case_statement.md b/contrib/advanced-python/match_case_statement.md index d4ad861..691d23b 100644 --- a/contrib/advanced-python/match_case_statement.md +++ b/contrib/advanced-python/match_case_statement.md @@ -20,3 +20,60 @@ A match statement takes a statement which compares it to the various cases and t As discussed earlier, match case statements use pattern matching where the patterns consist of sequences, mappings, primitive data types as well as class instances. The structural pattern matching uses declarative approach and it nexplicitly states the conditions for the patterns to match with the data. ### Patterns with a Literal +#### Generic Case +`sample text` is passed as a literal in the `match` block. There are two cases and a wildcard case mentioned. +```python +match 'sample text': + case 'sample text': + print('sample text') + case 'sample': + print('sample') + case _: + print('None found') +``` +The `sample text` case is satisfied as it matches with the literal `sample text` described in the `match` block. + +O/P: +``` +sample text +``` + +#### Using OR +Taking another example, `|` can be used as OR to include multiple patterns in a single case statement where the multiple patterns all lead to a similar task. + +The below code snippets can be used interchangebly and generate the similar output. The latter is more consive and readible. +```python +match 'e': + case 'a': + print('vowel') + case 'e': + print('vowel') + case 'i': + print('vowel') + case 'o': + print('vowel') + case 'u': + print('vowel') + case _: + print('consonant') +``` +```python +match 'e': + case 'a' | 'e' | 'i' | 'o' | 'u': + print('vowel') + case _: + print('consonant') +``` +O/P: +``` +vowel +``` + +#### Without wildcard +When in a `match` block, there is no wildcard case present there are be two cases of match being present or not. If the match doesn't exist, the behaviour is a no-op. +```python +match 'c': + case 'a' | 'e' | 'i' | 'o' | 'u': + print('vowel') +``` +The output will be blank as a no-op occurs. From 5f57b24ac03006216a366219e09ea0566e231ab8 Mon Sep 17 00:00:00 2001 From: SAM <60264918+SAM-DEV007@users.noreply.github.com> Date: Tue, 4 Jun 2024 17:44:13 +0530 Subject: [PATCH 05/11] Update match_case_statement.md Added two more sections. Patterns with a literal and a variable, and patterns with classes. --- .../advanced-python/match_case_statement.md | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/contrib/advanced-python/match_case_statement.md b/contrib/advanced-python/match_case_statement.md index 691d23b..57f6bfb 100644 --- a/contrib/advanced-python/match_case_statement.md +++ b/contrib/advanced-python/match_case_statement.md @@ -77,3 +77,86 @@ match 'c': print('vowel') ``` The output will be blank as a no-op occurs. + +### Patterns with a Literal and a Variable +Pattern matching can be done by unpacking the assignments and also bind variables with it. +```python +def get_names(names: str) -> None: + match names: + case ('Bob', y): + print(f'Hello {y}') + case (x, 'John'): + print(f'Hello {x}') + case (x, y): + print(f'Hello {x} and {y}') + case _: + print('Invalid') +``` +Here, the `names` is a tuple that contains two names. The `match` block unpacks the tuple and binds `x` and `y` based on the patterns. A wildcard case prints `Invalid` if the condition is not satisfied. + +O/P: + +In this example, the above code snippet with the parameter `names` as below and the respective output. +``` +>>> get_names(('Bob', 'Max')) +Hello Max + +>>> get_names(('Rob', 'John')) +Hello Rob + +>>> get_names(('Rob', 'Max')) +Hello Rob and Max + +>>> get_names(('Rob', 'Max', 'Bob')) +Invalid +``` + +### Patterns with Classes +Class structures can be used in `match` block for pattern matching. The class members can also be binded with a variable to perform certain operations. For the class structure: +```python +class Person: + def __init__(self, name, age): + self.name = name + self.age = age +``` +The match case example illustrates the generic working as well as the binding of variables with the class members. +```python +def get_class(cls: Person) -> None: + match cls: + case Person(name='Bob', age=18): + print('Hello Bob with age 18') + case Person(name='Max', age=y): + print(f'Age is {y}') + case Person(name=x, age=18): + print(f'Name is {x}') + case Person(name=x, age=y): + print(f'Name and age is {x} and {y}') + case _: + print('Invalid') +``` +O/P: +``` +>>> get_class(Person('Bob', 18)) +Hello Bob with age 18 + +>>> get_class(Person('Max', 21)) +Age is 21 + +>>> get_class(Person('Rob', 18)) +Name is Rob + +>>> get_class(Person('Rob', 21)) +Name and age is Rob and 21 +``` +Now, if a new class is introduced in the above code snippet like below. +```python +class Pet: + def __init__(self, name, animal): + self.name = name + self.animal = animal +``` +The patterns will not match the cases and will trigger the wildcard case for the original code snippet above with `get_class` function. +``` +>>> get_class(Pet('Tommy', 'Dog')) +Invalid +``` From e5c88286d5b72b0e0e51e4f1c889544b41c91ef9 Mon Sep 17 00:00:00 2001 From: SAM <60264918+SAM-DEV007@users.noreply.github.com> Date: Tue, 4 Jun 2024 18:02:50 +0530 Subject: [PATCH 06/11] Update match_case_statement.md Added remaining topic headings --- contrib/advanced-python/match_case_statement.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/contrib/advanced-python/match_case_statement.md b/contrib/advanced-python/match_case_statement.md index 57f6bfb..6941d98 100644 --- a/contrib/advanced-python/match_case_statement.md +++ b/contrib/advanced-python/match_case_statement.md @@ -160,3 +160,14 @@ The patterns will not match the cases and will trigger the wildcard case for the >>> get_class(Pet('Tommy', 'Dog')) Invalid ``` + +### Nested Patterns + +### Complex Patterns +#### Wildcard + +#### Guard + +## Summary + +## Further Reading From ffcc45ad986b70a5b1b39cc515bb7e7230db3c4d Mon Sep 17 00:00:00 2001 From: SAM <60264918+SAM-DEV007@users.noreply.github.com> Date: Tue, 4 Jun 2024 18:28:39 +0530 Subject: [PATCH 07/11] Update match_case_statement.md Added nested patterns --- .../advanced-python/match_case_statement.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/contrib/advanced-python/match_case_statement.md b/contrib/advanced-python/match_case_statement.md index 6941d98..22eeef9 100644 --- a/contrib/advanced-python/match_case_statement.md +++ b/contrib/advanced-python/match_case_statement.md @@ -162,6 +162,33 @@ Invalid ``` ### Nested Patterns +The patterns can be nested via various means. It can include the mix of the patterns mentioned earlier or can be symmetrical across. A basic of the nested pattern of a list with Patterns with a Literal and Variable is taken. Classes and Iterables can laso be included. +```python +def get_points(points: list) -> None: + match points: + case []: + print('Empty') + case [x]: + print(f'One point {x}') + case [x, y]: + print(f'Two points {x} and {y}') + case _: + print('More than two points') +``` +O/P: +``` +>>> get_points([]) +Empty + +>>> get_points([1]) +One point 1 + +>>> get_points([1, 2]) +Two points 1 and 2 + +>>> get_points([1, 2, 3]) +More than two points +``` ### Complex Patterns #### Wildcard From d345d0339f7a2bd5eea818f5a42bc4e0c5d9f5f7 Mon Sep 17 00:00:00 2001 From: SAM <60264918+SAM-DEV007@users.noreply.github.com> Date: Tue, 4 Jun 2024 19:14:09 +0530 Subject: [PATCH 08/11] Update match_case_statement.md Added the content to remaining sections --- .../advanced-python/match_case_statement.md | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/contrib/advanced-python/match_case_statement.md b/contrib/advanced-python/match_case_statement.md index 22eeef9..cd7bc64 100644 --- a/contrib/advanced-python/match_case_statement.md +++ b/contrib/advanced-python/match_case_statement.md @@ -191,10 +191,60 @@ More than two points ``` ### Complex Patterns +Complex patterns are also supported in the pattern matching sequence. The complex does not mean complex numbers but rather the structure which makes the readibility to seem complex. + #### Wildcard +The wildcard used till now are in the form of `case _` where the wildcard case is used if no match is found. Furthermore, the wildcard `_` can also be used as a placeholder in complex patterns. + +```python +def wildcard(value: tuple) -> None: + match value: + case ('Bob', age, 'Mechanic'): + print(f'Bob is mechanic of age {age}') + case ('Bob', age, _): + print(f'Bob is not a mechanic of age {age}') +``` +O/P: + +The value in the above snippet is a tuple with `(Name, Age, Job)`. If the job is Mechanic and the name is Bob, the first case is triggered. But if the job is different and not a mechanic, then the other case is triggered with the wildcard. +``` +>>> wildcard(('Bob', 18, 'Mechanic')) +Bob is mechanic of age 18 + +>>> wildcard(('Bob', 21, 'Engineer')) +Bob is not a mechanic of age 21 +``` #### Guard +A `guard` is when an `if` is added to a pattern. The evaluation depends on the truth value of the guard. + +`nums` is the tuple which contains two integers. A guard is the first case where it checks whether the first number is greater or equal to the second number in the tuple. If it is false, then it moves to the second case, where it concludes that the first number is smaller than the second number. +```python +def guard(nums: tuple) -> None: + match nums: + case (x, y) if x >= y: + print(f'{x} is greater or equal than {y}') + case (x, y): + print(f'{x} is smaller than {y}') + case _: + print('Invalid') +``` +O/P: +``` +>>> guard((1, 2)) +1 is smaller than 2 + +>>> guard((2, 1)) +2 is greater or equal than 1 + +>>> guard((1, 1)) +1 is greater or equal than 1 +``` ## Summary +The match case statements provide an elegant and readible format to perform operations on pattern matching as compared to `if-else` statements. They are also more versatile as they provide additional functionalities on the pattern matching operations like unpacking, class matching, iterables and iterators. It can also use positional arguments for checking the patterns. They provide a powerful and concise way to handle multiple conditions and perform pattern matching ## Further Reading +- [Python Match Case Statement - GeeksForGeeks](https://www.geeksforgeeks.org/python-match-case-statement/) +- [PEP 634 – Structural Pattern Matching: Specification](https://peps.python.org/pep-0634/) +- [PEP 636 – Structural Pattern Matching: Tutorial](https://peps.python.org/pep-0636/) From fe4ce4a34df72c800d12c624385069b27b689d11 Mon Sep 17 00:00:00 2001 From: SAM <60264918+SAM-DEV007@users.noreply.github.com> Date: Tue, 4 Jun 2024 19:16:29 +0530 Subject: [PATCH 09/11] Update match_case_statement.md Added further reading topic summary --- contrib/advanced-python/match_case_statement.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/advanced-python/match_case_statement.md b/contrib/advanced-python/match_case_statement.md index cd7bc64..b617f7a 100644 --- a/contrib/advanced-python/match_case_statement.md +++ b/contrib/advanced-python/match_case_statement.md @@ -245,6 +245,8 @@ O/P: The match case statements provide an elegant and readible format to perform operations on pattern matching as compared to `if-else` statements. They are also more versatile as they provide additional functionalities on the pattern matching operations like unpacking, class matching, iterables and iterators. It can also use positional arguments for checking the patterns. They provide a powerful and concise way to handle multiple conditions and perform pattern matching ## Further Reading +This article provides a brief introduction to the match case statements and the overview on the pattern matching operations. To know more, the below articles can be used for in-depth understanding of the topic. + - [Python Match Case Statement - GeeksForGeeks](https://www.geeksforgeeks.org/python-match-case-statement/) - [PEP 634 – Structural Pattern Matching: Specification](https://peps.python.org/pep-0634/) - [PEP 636 – Structural Pattern Matching: Tutorial](https://peps.python.org/pep-0636/) From 4f096eb6a64c5e798f04a68740c7a8aae39b048c Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sat, 8 Jun 2024 23:39:18 +0530 Subject: [PATCH 10/11] Update index.md --- contrib/advanced-python/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/advanced-python/index.md b/contrib/advanced-python/index.md index 59ea9b5..b093e44 100644 --- a/contrib/advanced-python/index.md +++ b/contrib/advanced-python/index.md @@ -12,7 +12,7 @@ - [Protocols](protocols.md) - [Exception Handling in Python](exception-handling.md) - [Generators](generators.md) -- [Match Case Statement](match_case_statement.md) +- [Match Case Statement](match-case.md) - [Closures](closures.md) - [Filter](filter-function.md) - [Reduce](reduce-function.md) From 7d18fe39d45bfdd2e4d432c8bc70b4c7496f7e2d Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sat, 8 Jun 2024 23:39:52 +0530 Subject: [PATCH 11/11] Update and rename match_case_statement.md to match-case.md --- .../advanced-python/{match_case_statement.md => match-case.md} | 1 - 1 file changed, 1 deletion(-) rename contrib/advanced-python/{match_case_statement.md => match-case.md} (95%) diff --git a/contrib/advanced-python/match_case_statement.md b/contrib/advanced-python/match-case.md similarity index 95% rename from contrib/advanced-python/match_case_statement.md rename to contrib/advanced-python/match-case.md index b617f7a..1b4f017 100644 --- a/contrib/advanced-python/match_case_statement.md +++ b/contrib/advanced-python/match-case.md @@ -247,6 +247,5 @@ The match case statements provide an elegant and readible format to perform oper ## Further Reading This article provides a brief introduction to the match case statements and the overview on the pattern matching operations. To know more, the below articles can be used for in-depth understanding of the topic. -- [Python Match Case Statement - GeeksForGeeks](https://www.geeksforgeeks.org/python-match-case-statement/) - [PEP 634 – Structural Pattern Matching: Specification](https://peps.python.org/pep-0634/) - [PEP 636 – Structural Pattern Matching: Tutorial](https://peps.python.org/pep-0636/)