Python의 구조 패턴 일치
![Python의 구조 패턴 일치](/img/Python/feature-image---structural-pattern-matching-in-python.webp)
Python 3.10 이전에는 다른 프로그래밍 언어에서 스위치 케이스
라고 하는 구조적 패턴 일치를 사용하는 내장 방법이 없었습니다. Python 3.10 릴리스부터 match ... case
문을 사용하여 switch ... case
문을 에뮬레이트할 수 없습니다.
이 튜토리얼은 Python에서 구조적 패턴 일치와 그 중요성을 소개합니다. 또한 match ... case
문을 사용하여 시연하기 위해 다양한 패턴을 사용합니다.
구조 패턴 일치 소개 및 그 중요성
2021년 초부터 출시된 Python 3.9 이하 버전에서는 match
키워드를 사용할 수 없습니다. 당시 우리는 사전이나 중첩된 if/elif/else
문을 사용하여 switch ... case
를 시뮬레이션하는 데 익숙했습니다.
그러나 Python 3.10에는 구조적 패턴 일치(match ... case
문)라는 새로운 기능이 도입되었습니다. 이는 Java, C++ 및 기타 여러 프로그래밍 언어에서 사용하는 switch ... case
문과 동일합니다.
이 새로운 기능을 통해 간단하고 읽기 쉬우며 오류 발생 가능성이 최소화된 흐름 제어 문을 작성할 수 있습니다.
Python에서 구조 패턴 일치 사용
구조적 패턴 일치는 switch ... case
문으로 사용되며 이보다 더 강력합니다. 어떻게? 아래의 몇 가지 예를 살펴보고 다양한 상황에서 사용하는 방법을 알아보겠습니다.
match ... case
문의 기본 사용
예제 코드:
# >= Python 3.10
colour = "blue"
match colour:
case "green":
print("The specified colour is green")
case "white":
print("Wow, you've picked white")
case "green":
print("Great, you are going with green colour")
case "blue":
print("Blue like sky...")
출력:
Blue like sky...
여기에서 먼저 blue
를 포함하는 color
변수가 있습니다. 그런 다음 match
키워드를 사용합니다. 이 키워드는 color
변수의 값을 다양한 지정된 사례와 일치시킵니다. 각 사례는 case
키워드로 시작하여 비교하거나 확인하려는 패턴이 이어집니다.
패턴은 다음 중 하나일 수 있습니다.
- 리터럴 패턴
- 캡처 패턴
- 와일드카드 패턴
- 상수 값 패턴
- 시퀀스 패턴
- 매핑 패턴
- 클래스 패턴
- OR 패턴
- 해마 패턴
match ... case
문은 일치하는 첫 번째 case
아래의 코드만 실행합니다.
일치하는 case
가 없으면 어떻게 됩니까? 사용자는 그것에 대해 어떻게 알 수 있습니까? 이를 위해 다음과 같이 기본 case
를 가질 수 있습니다.
예제 코드:
# >= Python 3.10
colour = "yellow"
match colour:
case "green":
print("The specified colour is green")
case "white":
print("Wow, you've picked white")
case "green":
print("Great, you are going with green colour")
case "blue":
print("Blue like sky...")
case other:
print("No match found!")
출력:
No match found!
match ... case
를 사용하여 데이터 구조 감지 및 분해
예제 코드:
# >= Python 3.10
student = {"name": {"first": "Mehvish", "last": "Ashiq"}, "section": "B"}
match student:
case {"name": {"first": firstname}}:
print(firstname)
출력:
Mehvish
위의 예에서 구조적 패턴 일치는 다음 두 줄의 코드에서 작동합니다.
# >= Python 3.10
match student:
case {"name": {"first": firstname}}:
match ... case
문을 사용하여 student
데이터 구조에서 추출하여 학생의 이름을 찾습니다. 여기서 학생
은 학생의 정보를 담고 있는 사전입니다.
case
줄은 student
와 일치하는 패턴을 지정합니다. 위의 예를 고려하여 값이 새 사전인 "이름"
키가 있는 사전을 찾습니다.
이 중첩된 사전에는 값이 firstname
변수에 바인딩된 "first"
키가 포함되어 있습니다. 마지막으로 firstname
변수를 사용하여 값을 인쇄합니다.
더 깊이 관찰하면 여기에서 매핑 패턴을 배웠습니다. 어떻게? 매핑 패턴은 {"student": s, "emails": [*es]}
와 같으며 적어도 지정된 키 집합과 매핑을 일치시킵니다.
모든 하위 패턴이 해당 값과 일치하면 키에 해당하는 값과 일치하는 동안 하위 패턴 바인딩이 무엇이든 바인딩합니다. 추가 항목 캡처를 허용하려면 패턴 끝에 **rest
를 추가할 수 있습니다.
캡처 패턴 및 시퀀스 패턴과 함께 match ... case
사용
예제 코드:
# >= Python 3.10
def sum_list_of_numbers(numbers):
match numbers:
case []:
return 0
case [first, *rest]:
return first + sum_list_of_numbers(rest)
sum_list_of_numbers([1, 2, 3, 4])
출력:
10
여기에서 재귀 함수를 사용하여 캡처 패턴을 사용하여 지정된 패턴에 대한 일치 항목을 캡처하고 이름에 바인딩합니다.
이 코드 예제에서 첫 번째 case
는 빈 목록과 일치하는 경우 합계로 0
을 반환합니다. 두 번째 case
는 두 개의 캡처 패턴이 있는 시퀀스 패턴을 사용하여 목록을 여러 항목/요소 중 하나와 일치시킵니다.
여기에서 목록의 첫 번째 항목이 캡처되고 first
이름에 바인딩되는 반면 두 번째 캡처 패턴인 *rest
는 압축 풀기 구문을 사용하여 항목/요소의 수와 일치합니다.
rest
는 첫 번째 항목을 제외하고 숫자의 모든 항목/요소가 있는 목록에 바인딩됩니다. 출력을 얻기 위해 위에서 주어진 숫자 목록을 전달하여 sum_list_of_numbers()
함수를 호출합니다.
와일드카드 패턴과 함께 match ... case
사용
예제 코드:
# >= Python 3.10
def sum_list_of_numbers(numbers):
match numbers:
case []:
return 0
case [first, *rest]:
return first + sum_list_of_numbers(rest)
case _:
incorrect_type = numbers.__class__.__name__
raise ValueError(
f"Incorrect Values. We Can only Add lists of numbers,not {incorrect_type!r}"
)
sum_list_of_numbers({"1": "2", "3": "4"})
출력:
ValueError: Incorrect Values. We Can only Add lists of numbers, not 'dict'
우리는 match ... case
문의 기본 사용법을 배우면서 와일드카드 패턴 사용의 개념을 배웠지만 와일드카드 패턴 용어를 소개하지 않았습니다. 처음 두 사례가 일치하지 않는 시나리오를 상상해 보십시오. 최종 사례
로 포괄 패턴이 있어야 합니다.
예를 들어 목록 대신 다른 유형의 데이터 구조를 얻으면 오류를 발생시키고 싶습니다. 여기에서 _
를 와일드카드 패턴으로 사용할 수 있으며 이름에 바인딩하지 않고 모든 항목과 일치합니다. 사용자에게 알리기 위해 이 마지막 사례
에 오류 처리를 추가합니다.
당신은 무엇을 말합니까? 우리의 패턴이 잘 어울리나요? 다음과 같이 문자열 값 목록을 전달하여 sum_list_of_numbers()
함수를 호출하여 테스트해 보겠습니다.
sum_list_of_numbers(["1", "2", "3", "4"])
다음 오류가 발생합니다.
TypeError: can only concatenate str (not "int") to str
따라서 패턴이 여전히 완벽하지 않다고 말할 수 있습니다. 왜? 목록 유형 데이터 구조를 sum_list_of_numbers()
함수에 전달하지만 예상한 int 유형이 아닌 문자열 유형 값을 갖기 때문입니다.
해결 방법은 다음 섹션을 참조하십시오.
클래스 패턴과 함께 match ... case
사용
예제 코드:
# >= Python 3.10
def sum_list_of_numbers(numbers):
match numbers:
case []:
return 0
case [int(first), *rest]:
return first + sum_list_of_numbers(rest)
case _:
raise ValueError(f"Incorrect values! We can only add lists of numbers")
sum_list_of_numbers(["1", "2", "3", "4"])
출력:
ValueError: Incorrect values! We can only add lists of numbers
기본 사례(첫 번째 case
)는 0
을 반환합니다. 따라서 합산은 숫자로 추가할 수 있는 유형에 대해서만 작동합니다. Python은 텍스트 문자열과 숫자를 추가하는 방법을 모릅니다.
따라서 클래스 패턴을 사용하여 정수만 일치하도록 패턴을 제한할 수 있습니다. 클래스 패턴은 매핑 패턴과 유사하지만 키 대신 속성을 일치시킵니다.
OR 패턴과 함께 match ... case
사용
예제 코드:
# >= Python 3.10
def sum_list_of_numbers(numbers):
match numbers:
case []:
return 0
case [int(first) | float(first), *rest]:
return first + sum_list_of_numbers(rest)
case _:
raise ValueError(f"Incorrect values! We can only add lists of numbers")
sum_list_of_numbers()
함수가 int 유형이든 float 유형이든 상관없이 값 목록에 대해 작동하도록 만들고 싶다고 가정합니다. 파이프 기호(|
)로 표시되는 OR 패턴을 사용합니다.
위의 코드는 지정된 목록에 int 또는 float 유형 값 이외의 값이 포함된 경우 ValueError
를 발생시켜야 합니다. 아래 세 가지 시나리오를 모두 고려하여 테스트해 보겠습니다.
테스트 1: int 유형 값이 있는 목록을 전달합니다.
sum_list_of_numbers([1, 2, 3, 4]) # output is 10
테스트 2: float 유형 값이 있는 목록을 전달합니다.
sum_list_of_numbers([1.0, 2.0, 3.0, 4.0]) # output is 10.0
테스트 3: int 및 float 유형을 제외한 다른 유형의 목록을 전달합니다.
sum_list_of_numbers(["1", "2", "3", "4"])
# output is ValueError: Incorrect values! We can only add lists of numbers
보시다시피 sum_list_of_numbers()
함수는 OR 패턴을 사용하기 때문에 int 및 float 유형 값 모두에 대해 작동합니다.
리터럴 패턴과 함께 match ... case
사용
예제 코드:
# >= Python 3.10
def say_hello(name):
match name:
case "Mehvish":
print(f"Hi, {name}!")
case _:
print("Howdy, stranger!")
say_hello("Mehvish")
출력:
Hi, Mehvish!
이 예제에서는 match ... case
문의 기본 사용법을 학습하는 동안 이미 수행한 것처럼 명시적 숫자 또는 문자열과 같은 리터럴 객체와 일치하는 리터럴 패턴을 사용합니다.
가장 기본적인 유형의 패턴이며 Java, C++ 및 기타 프로그래밍 언어와 유사한 switch ... case
문을 시뮬레이션할 수 있습니다. 이 페이지를 방문하여 모든 패턴에 대해 알아볼 수 있습니다.