Language/Python

[Python] 파이썬 3.10 새로운 기능

개발기록자 2023. 5. 10.

파이썬 3.10은 이전 버전과 비교해 많은 변화와 새로운 기능이 도입되어 파이썬 개발자들에게 더욱 직관적이고 효율적인 개발을 가능하게 합니다. 파이썬 3.10에서는 match-case문의 등장을 비롯하여 타입 힌트, 괄호로 묶인 컨텍스트 관리자 등 다양한 기능이 추가되었습니다. 이번 글에서는 파이썬 3.10에 도입된 새로운 기능들에 대해 알아보겠습니다.


1. 괄호로 묶인 컨텍스트 관리자(Parenthesized context managers)

이전에는 `with`문 다음에 한 개의 Context Manager만 사용할 수 있었지만, 3.10에서는 괄호로 묶어 여러 개의 Context Manger를 사용할 수 있게 되었습니다. 괄호로 묶인 Context Manager를 사용하면 코드를 더 간결하게 작성할 수 있습니다.

with (CtxManager() as example):
    ...

with (
    CtxManager1(),
    CtxManager2()
):
    ...

with (CtxManager1() as example,
      CtxManager2()):
    ...

with (CtxManager1(),
      CtxManager2() as example):
    ...

with (
    CtxManager1() as example1,
    CtxManager2() as example2
):
    ...

with (
    CtxManager1() as example1,
    CtxManager2() as example2,
    CtxManager3() as example3,
):
    ...

2. 더 나은 오류 메시지(Better error messages)

이전에는 오류 메시지가 모호하거나 이해하기 어려웠지만, 3.10에서는 오류 메시지가 자세하고 명확해졌습니다. 아래에 몇 가지 예시를 보며 알아보겠습니다.

 

1) SyntaxErrors

expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
            38: 4, 39: 4, 45: 5, 46: 5, 47: 5, 48: 5, 49: 5, 54: 6,
some_other_code = foo()


# SyntaxError - 3.10 이전
File "example.py", line 3
    some_other_code = foo()
                    ^
SyntaxError: invalid syntax


# SyntaxError - 3.10
File "example.py", line 1
    expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
               ^
SyntaxError: '{' was never closed

기존에는 괄호가 닫히지 않는 등 SyntaxError가 발생했을 때 발생한 위치와 에러 메시지만 출력되었지만, 3.10에서는 SyntaxError의 원인이 되는 부분과 SyntaxError의 원인 등 자세한 정보를 알려줍니다.

 

foo(x, z for z in range(10), t, w)


# SyntaxError - 3.10 이전
  File "<stdin>", line 1
    foo(x, z for z in range(10), t, w)
           ^
SyntaxError: Generator expression must be parenthesized


# SyntaxError - 3.10
  File "<stdin>", line 1
    foo(x, z for z in range(10), t, w)
           ^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized

SyntaxError가 발생했을 경우 발생한 위치에 강조 표시를 했지만, 3.10에서는 구문 오류 자체를 구성하는 표현식의 전체 오류 범위를 강조 표시합니다.

 

2) IndentationErrors

기존에는 들여쓰기 오류가 발생했다는 정보만 제공했지만, 3.10에서는 어떤 위치에서 오류가 발생했는지 등 더욱 자세한 정보를 제공합니다.

def foo():
   if lel:
   x = 2

# IndentationError - 3.10
  File "<stdin>", line 3
    x = 2
    ^
IndentationError: expected an indented block after 'if' statement in line 2

 

3) AttributeErrors

기존에는 AttributeErrors가 발생할 경우 속성 이름과 관련된 정보만 제공되었습니다. 3.10에서는 오브젝트 추천과 같은 정보도 제공됩니다.

collections.namedtoplo

# AttributeError - 3.10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'collections' has no attribute 'namedtoplo'. Did you mean: namedtuple?

 

4) NameErrors

기존에는 NameErrors가 발생할 경우 해당 변수 이름만 제공되었지만, 3.10에서는 비슷한 이름의 변수와 같은 정보도 제공됩니다.

schwarzschild_black_hole = None
schwarschild_black_hole

# NameError - 3.10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'schwarschild_black_hole' is not defined. Did you mean: schwarzschild_black_hole?

3. 구조적 패턴 매칭(Structural Pattern Matching)

파이썬 3.10에서는 새로운 기능 중 하나로 구조적 패턴 매칭(Structural Pattern Matching)을 도입했습니다. 구조적 패턴 매칭은 복잡한 조건문을 작성할 때 코드의 가독성과 유지 보수성을 높일 수 있는 매우 유용한 기능입니다. 기본적인 몇 가지 패턴을 보면서 알아보겠습니다.

 

구조적 패턴 매칭의 일반 구문은 다음과 같습니다.

match subject:
    case <pattern_1>:
        <action_1>
    case <pattern_2>:
        <action_2>
    case <pattern_3>:
        <action_3>
    case _:
        <action_wildcard>

 

1) Simple pattern

가장 간단하고 단순한 형태의 패턴 매칭입니다. `_`는 wildcard로 어떠한 값이든 항상 일치하도록 합니다.

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 401 | 403 | 404:
    		return "Not allowed"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"

 

2) Behavior without the wildcard

`_`(wildcard)가 없는 패턴 매칭입니다.

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"

 

3) Patterns with a literal and variable

특정 값이나 변수를 사용하여 데이터 유형에서 패턴을 매칭합니다.

# point is an (x, y) tuple
match point:
    case (0, 0):
        print("Origin")
    case (0, y):
        print(f"Y={y}")
    case (x, 0):
        print(f"X={x}")
    case (x, y):
        print(f"X={x}, Y={y}")
    case _:
        raise ValueError("Not a point")

 

4) Patterns and classes

구조적 패턴 매칭에서 클래스와 관련된 매칭입니다. 클래스의 속성을 기반으로 패턴 매칭을 할 수 있습니다.

class Point:
    x: int
    y: int

def location(point):
    match point:
        case Point(x=0, y=0):
            print("Origin is the point's location.")
        case Point(x=0, y=y):
            print(f"Y={y} and the point is on the y-axis.")
        case Point(x=x, y=0):
            print(f"X={x} and the point is on the x-axis.")
        case Point():
            print("The point is located somewhere else on the plane.")
        case _:
            print("Not a point")

 

5) Guard

구조적 패턴 매칭에서 특정 패턴에 추가적인 조건을 지정하는 것입니다. Guard는 `if`문으로 구성 되며 조건식이 참일 경우에만 해당 패턴에 대한 동작이 실행됩니다.

match point:
    case Point(x, y) if x == y:
        print(f"The point is located on the diagonal Y=X at {x}.")
    case Point(x, y):
        print(f"Point is not on the diagonal.")

4. 타입 힌트와 관련된 새로운 기능(New Features Related to Type Hints)

파이썬 3.10 업데이트에서는 타입 힌트에 관련된 새로운 기능이 추가되었습니다. 새로운 기능의 추가로 코드 작성 시 타입 안정성을 높여주며, 코드의 가독성과 유지보수성이 높아졌습니다. 아래는 추가된 몇 가지 기능입니다.

 

4.1 New Type Union Operator

기존에는 타입 힌트에서 Union을 사용하여 두 개 이상의 타입을 합칠 수 있었지만, 3.10에서는 `|` 기호를 사용하여 동일하게 사용할 수 있습니다. New Type Union Operator를 사용하면 코드가 더 간경해지고, 가독성이 높아집니다.

# Union Operator - 3.10 이전
from typing import Union

def square(number: Union[int, float]) -> Union[int, float]:
    return number ** 2

print(square(5.0)) # 25.0
print(square(3)) # 9


# New Type Union Operator - 3.10
def square(number: int | float) -> int | float:
    return number ** 2

print(square(5.0)) # 25.0
print(square(3)) # 9

 

4.2 TypeAlias

파이썬 3.10에서는 새로운 타입 힌트의 기능 중 하나로 `TypeAlias`가 추가되었습니다. 이 기능은 타입 힌트에서 자주 사용되는 복잡한 타입 이름을 간결하게 정의할 수 있는 방법을 제공합니다.

# Python 3.10 미만에서의 코드
def process_person_info(info: tuple[str, int]) -> None:
    name, age = info
    print(f"Name: {name}, Age: {age}")

info_tuple = ('Alice', 20)
process_person_info(info_tuple) # Name: Alice, Age: 20


# Python 3.10에서 TypeAlias를 사용한 코드
from typing import TypeAlias, Tuple

PersonInfo : TypeAlias = Tuple[str, int]

def process_person_info(info: PersonInfo) -> None:
    name, age = info
    print(f"Name: {name}, Age: {age}")

info_tuple = ('Alice', 20)
process_person_info(info_tuple) # Name: Alice, Age: 20

이번 글에서는 파이썬 3.10에 추가된 새로운 기능들을 중심으로 간단하게 살펴보았습니다. 파이썬 3.10에서는 많은 변화가 있었고, 이러한 변화와 새로운 기능들은 개발자들이 코딩 작업을 더욱 효율적으로 수행할 수 있도록 도움을 줄 것입니다. 


참조

 

What’s New In Python 3.10 — Python 3.10.11 documentation

Parenthesized context managers Using enclosing parentheses for continuation across multiple lines in context managers is now supported. This allows formatting a long collection of context managers in multiple lines in a similar way as it was previously pos

docs.python.org

 

 

 

댓글