2021.10.06

패턴 매칭 지원 外··· '파이썬 3.10', 무엇이 달라졌을까

Serdar Yegulalp | InfoWorld
파이썬의 최신 버전(v3.10)은 강력한 패턴 매칭, 개선된 오류 보고, 래핑된 함수에 관한 스마트한 입력 구문 등을 제공한다.  

파이썬 3.10(Python 3.10)이 지난 10월 4일 출시됐다. 용감무쌍한 파이썬 개발자라고 해도 적절한 예방 조치(예: 가상 환경 사용 등)와 함께 코드를 테스트하는 게 좋다. 

엄밀히 말해서 파이썬 3.10에는 진정으로 새로운 기능이 많진 않지만 그중 하나인 ‘구조적 패턴 매칭(Structural Pattern Matching)’은 async 이후 언어 구문에 가장 중요한 추가 기능일지도 모른다. 여기에서는 파이썬 3.10의 모든 새로운 기능과 코드를 지원하는 방법을 살펴본다. 
 
ⓒGetty Images

구조적 패턴 매칭 
구조적 패턴 매칭을 사용하면 가능한 값 세트 중 하나와 변수를 일치시킬 수 있다. 또 값의 패턴(예: 특정 속성이 특정 값으로 설정된 객체)과도 일치시킬 수 있다. 이를 통해 가능성의 범위가 크게 확장되고, 다양한 시나리오를 포함하는 코드를 신속하게 작성할 수 있다. 예는 아래와 같다. 패턴 매칭을 사용하는 방법에 관한 자세한 내용은 이곳에서 확인할 수 있다. 
 
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")

더 정확해진 오류 보고
파이썬의 오류 보고는 오랫동안 파서(parser)에 좌우돼 왔다. 개발팀은 파이썬 3.9에서 ‘더 빠르고, 더 강력하며, 파이썬 팀이 유지관리하기 더 쉽고, 내부 해킹이 덜한’ 완전히 새로운 파서를 선보였다. 

이 새로운 파서가 개발자들에게 제공하는 한 가지 큰 보너스는 훨씬 더 정확하고 유용한 오류 메시지다. 파이썬 3.8에서 다음의 코드는 구문 오류를 생성했다. 
 
print ("Hello"
print ("What's going on?")

  File ".\test.py", line 2
    print ("What's going on?")
    ^
SyntaxError: invalid syntax

실제 문제는 한 줄 앞에 있기 때문에 이는 별로 도움이 되지 않았다. 파이썬 3.10은 훨씬 더 유용한 오류를 생성한다. 
 
File ".\test.py", line 1
    print ("Hello"
          ^
SyntaxError: '(' was never closed

개발팀에 따르면 파서에 의해 생성된 오류 중 많은 부분이 이러한 맥락에서 개선됐다. 더 정확한 오류 정보를 제공할 뿐만 아니라 오류가 실제로 발생한 위치에 대해서도 더 정확한 정보를 지원한다. 

매개변수 사양 변수 
타입 정보로 코드에 주석을 추가하는 데 쓰이는 파이썬의 입력 모듈을 사용하면 호출 가능한 타입(예: 함수 등)을 설명할 수 있다. 하지만 해당 타입 정보는 호출 가능한 객체(callable)에 걸쳐 전파될 수 없다. 이는 함수 데코레이터 등에 주석을 달기 어렵게 만든다. 

입력에 새로 추가된 2가지, typing.ParamSpectyping.Concatenate를 사용하면 호출 가능한 객체에 추상적인 타입 정의 정보로 주석을 달 수 있다. PEP 문서에서 가져온 이 새로운 기능의 예는 다음과 같다. 
 
from typing import Awaitable, Callable, TypeVar

R = TypeVar("R")

def add_logging(f: Callable[..., R]) -> Callable[..., Awaitable[R]]:
  async def inner(*args: object, **kwargs: object) -> R:
    await log_to_database()
    return f(*args, **kwargs)
  return inner

@add_logging
def takes_int_str(x: int, y: str) -> int:
  return x + 7

await takes_int_str(1, "A")
await takes_int_str("B", 2) # fails at runtime

데코레이터가 처리하는 함수에 어떤 종류의 타입을 전달하는지 적절한 세부 정보를 린터에 제공할 수 없기 때문에 린터는 takes_int_str의 두 번째 인스턴스에서 잘못된 유형을 잡을 수 없다. 다음은 이 코드가 새로운 매개변수 사양 변수 구문과 함께 작동하는 방법이다. 
 
from typing import Awaitable, Callable, ParamSpec, TypeVar

P = ParamSpec("P")
R = TypeVar("R")

def add_logging(f: Callable[P, R]) -> Callable[P, Awaitable[R]]:
  async def inner(*args: P.args, **kwargs: P.kwargs) -> R:
    await log_to_database()
    return f(*args, **kwargs)
  return inner

@add_logging
def takes_int_str(x: int, y: str) -> int:
  return x + 7

await takes_int_str(1, "A") # Accepted
await takes_int_str("B", 2) # Correctly rejected by the type checker

ParamSpec을 사용하면 위치 인수와 키워드 인수를 캡처할 곳을 지정할 수 있다. Concatenate은 일반적으로 데코레이터와 함께 수행되는 인수를 추가 또는 제거하는 방법을 나타내는 데 사용할 수 있다. 

이 밖에 파이썬 3.10의 다른 주요 변경사항은 아래와 같다. 

• 이제 유니온 타입을 Union[X,Y] 대신 간결하게 X|Y로 작성할 수 있다(PEP 604).

• 여러 이터러블(iterables)의 결과를 하나로 묶는 zip 빌트인에 strict 키워드가 추가됐다. True로 설정하면 이터러블 중 하나가 다른 이러터블보다 먼저 소진되는 경우 zip에서 예외를 발생시킨다 (PEP 618). 

with 문이 이제 여러 줄의 괄호 구문을 지원한다(BPO-12782). 

• 이제 변수를 타입 별칭으로 선언할 수 있다. 이를 통해 선행 참조나 잘못된 타입이 관련된 경우를 구별할 수 있다(PEP 613).

• C파이썬(CPython)을 구축하려면 오픈SSL(OpenSSL) 1.1.1 이상의 버전이 필요하다. 이는 C파이썬의 주요 종속성 중 하나를 현대화한다(PEP 644).

ciokr@idg.co.kr







 



2021.10.06

패턴 매칭 지원 外··· '파이썬 3.10', 무엇이 달라졌을까

Serdar Yegulalp | InfoWorld
파이썬의 최신 버전(v3.10)은 강력한 패턴 매칭, 개선된 오류 보고, 래핑된 함수에 관한 스마트한 입력 구문 등을 제공한다.  

파이썬 3.10(Python 3.10)이 지난 10월 4일 출시됐다. 용감무쌍한 파이썬 개발자라고 해도 적절한 예방 조치(예: 가상 환경 사용 등)와 함께 코드를 테스트하는 게 좋다. 

엄밀히 말해서 파이썬 3.10에는 진정으로 새로운 기능이 많진 않지만 그중 하나인 ‘구조적 패턴 매칭(Structural Pattern Matching)’은 async 이후 언어 구문에 가장 중요한 추가 기능일지도 모른다. 여기에서는 파이썬 3.10의 모든 새로운 기능과 코드를 지원하는 방법을 살펴본다. 
 
ⓒGetty Images

구조적 패턴 매칭 
구조적 패턴 매칭을 사용하면 가능한 값 세트 중 하나와 변수를 일치시킬 수 있다. 또 값의 패턴(예: 특정 속성이 특정 값으로 설정된 객체)과도 일치시킬 수 있다. 이를 통해 가능성의 범위가 크게 확장되고, 다양한 시나리오를 포함하는 코드를 신속하게 작성할 수 있다. 예는 아래와 같다. 패턴 매칭을 사용하는 방법에 관한 자세한 내용은 이곳에서 확인할 수 있다. 
 
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")

더 정확해진 오류 보고
파이썬의 오류 보고는 오랫동안 파서(parser)에 좌우돼 왔다. 개발팀은 파이썬 3.9에서 ‘더 빠르고, 더 강력하며, 파이썬 팀이 유지관리하기 더 쉽고, 내부 해킹이 덜한’ 완전히 새로운 파서를 선보였다. 

이 새로운 파서가 개발자들에게 제공하는 한 가지 큰 보너스는 훨씬 더 정확하고 유용한 오류 메시지다. 파이썬 3.8에서 다음의 코드는 구문 오류를 생성했다. 
 
print ("Hello"
print ("What's going on?")

  File ".\test.py", line 2
    print ("What's going on?")
    ^
SyntaxError: invalid syntax

실제 문제는 한 줄 앞에 있기 때문에 이는 별로 도움이 되지 않았다. 파이썬 3.10은 훨씬 더 유용한 오류를 생성한다. 
 
File ".\test.py", line 1
    print ("Hello"
          ^
SyntaxError: '(' was never closed

개발팀에 따르면 파서에 의해 생성된 오류 중 많은 부분이 이러한 맥락에서 개선됐다. 더 정확한 오류 정보를 제공할 뿐만 아니라 오류가 실제로 발생한 위치에 대해서도 더 정확한 정보를 지원한다. 

매개변수 사양 변수 
타입 정보로 코드에 주석을 추가하는 데 쓰이는 파이썬의 입력 모듈을 사용하면 호출 가능한 타입(예: 함수 등)을 설명할 수 있다. 하지만 해당 타입 정보는 호출 가능한 객체(callable)에 걸쳐 전파될 수 없다. 이는 함수 데코레이터 등에 주석을 달기 어렵게 만든다. 

입력에 새로 추가된 2가지, typing.ParamSpectyping.Concatenate를 사용하면 호출 가능한 객체에 추상적인 타입 정의 정보로 주석을 달 수 있다. PEP 문서에서 가져온 이 새로운 기능의 예는 다음과 같다. 
 
from typing import Awaitable, Callable, TypeVar

R = TypeVar("R")

def add_logging(f: Callable[..., R]) -> Callable[..., Awaitable[R]]:
  async def inner(*args: object, **kwargs: object) -> R:
    await log_to_database()
    return f(*args, **kwargs)
  return inner

@add_logging
def takes_int_str(x: int, y: str) -> int:
  return x + 7

await takes_int_str(1, "A")
await takes_int_str("B", 2) # fails at runtime

데코레이터가 처리하는 함수에 어떤 종류의 타입을 전달하는지 적절한 세부 정보를 린터에 제공할 수 없기 때문에 린터는 takes_int_str의 두 번째 인스턴스에서 잘못된 유형을 잡을 수 없다. 다음은 이 코드가 새로운 매개변수 사양 변수 구문과 함께 작동하는 방법이다. 
 
from typing import Awaitable, Callable, ParamSpec, TypeVar

P = ParamSpec("P")
R = TypeVar("R")

def add_logging(f: Callable[P, R]) -> Callable[P, Awaitable[R]]:
  async def inner(*args: P.args, **kwargs: P.kwargs) -> R:
    await log_to_database()
    return f(*args, **kwargs)
  return inner

@add_logging
def takes_int_str(x: int, y: str) -> int:
  return x + 7

await takes_int_str(1, "A") # Accepted
await takes_int_str("B", 2) # Correctly rejected by the type checker

ParamSpec을 사용하면 위치 인수와 키워드 인수를 캡처할 곳을 지정할 수 있다. Concatenate은 일반적으로 데코레이터와 함께 수행되는 인수를 추가 또는 제거하는 방법을 나타내는 데 사용할 수 있다. 

이 밖에 파이썬 3.10의 다른 주요 변경사항은 아래와 같다. 

• 이제 유니온 타입을 Union[X,Y] 대신 간결하게 X|Y로 작성할 수 있다(PEP 604).

• 여러 이터러블(iterables)의 결과를 하나로 묶는 zip 빌트인에 strict 키워드가 추가됐다. True로 설정하면 이터러블 중 하나가 다른 이러터블보다 먼저 소진되는 경우 zip에서 예외를 발생시킨다 (PEP 618). 

with 문이 이제 여러 줄의 괄호 구문을 지원한다(BPO-12782). 

• 이제 변수를 타입 별칭으로 선언할 수 있다. 이를 통해 선행 참조나 잘못된 타입이 관련된 경우를 구별할 수 있다(PEP 613).

• C파이썬(CPython)을 구축하려면 오픈SSL(OpenSSL) 1.1.1 이상의 버전이 필요하다. 이는 C파이썬의 주요 종속성 중 하나를 현대화한다(PEP 644).

ciokr@idg.co.kr







 

X