Hello World!

Python 3.11 달라진 점 - 업데이트

by PyTong

속도

문서에 따르면 3.10에 비해 10% ~ 60% 빨라졌다. 즉 1.25 배 빨라졌다

 

 

예외 처리 새 구문 (except*) 

예외문에 대한 그룹을 설정할 수 있고, 한번에 여러 예외를 받을 수 있다.또한 출력문을 예쁘게 그려준다

def f():
    raise ExceptionGroup(
        "group1",
        [
            OSError(1),
            SystemError(2),
            ExceptionGroup(
                "group2",
                [
                    OSError(3),
                    RecursionError(4)
                ]
            )
        ]
    )

try:
    f()
except* OSError as e:
    print("There were OSErrors")
except* SystemError as e:
    print("There were SystemErrors")

There were OSErrors
There were SystemErrors
  + Exception Group Traceback (most recent call last):
  |   File "<stdin>", line 2, in <module>
  |   File "<stdin>", line 2, in f
  | ExceptionGroup: group1
  +-+---------------- 1 ----------------
    | ExceptionGroup: group2
    +-+---------------- 1 ----------------
      | RecursionError: 4
      +------------------------------------

# tomlib 추가

데이터 직렬화 포맷인 TOML을 파싱할 수 있는 내장 라이브러리가 추가되었다. 

import tomllib

with open("pyproject.toml", "rb") as f:
    data = tomllib.load(f)

유사 데이터  JSON, YAML과 비교하면

특징 JSON YAML TOML
포맷 종류 데이터 교환 인간이 읽기 쉬운 데이터 설정 파일용
문법 엄격하고 간결한 사용자 친화적이고 유연한 키-값 쌍
주석 처리 지원하지 않음 지원 지원
데이터 타입 기본적인 타입 (문자열, 숫자, 객체, 배열, 불리언, 널) 풍부한 타입 (JSON 타입 지원 및 이진 데이터 등) 풍부한 타입 (기본 타입 및 날짜 지원)
가독성 중괄호와 따옴표 때문에 가독성이 떨어짐 최소한의 구두점으로 매우 가독성이 좋음 명확한 구조로 가독성이 좋음
작성 용이성 엄격한 문법으로 인해 작성이 덜 편리함 간결하고 쉬움 직관적이고 쉬움
파일 확장자 .json .yaml 또는 .yml .toml
사용처 웹 API, 현대 웹 애플리케이션의 설정 설정 파일, 데이터 직렬화 설정 파일, Rust 환경에서 더 일반적

 

에러 문구 개선

에러가 발생한 부분을 밑줄로 알려준다. 

사용자 입장에서 가장 크게 다가왔다.

x 변수에 대한 NoneType에서 어떤 변수의 x를 조회하다가 에러가 발생했는지, 밑줄로 알려준다.

Traceback (most recent call last):
  File "distance.py", line 11, in <module>
    print(manhattan_distance(p1, p2))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "distance.py", line 6, in manhattan_distance
    return abs(point_1.x - point_2.x) + abs(point_1.y - point_2.y)
                           ^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'x'

아쉬운 건 아래 코드에서

제로 디바이드에 대해 연산자 기준으로 알려준다. (변수 기준이었다면)

raceback (most recent call last):
  File "calculation.py", line 54, in <module>
    result = (x / y / z) * (a / b / c)
              ~~~~~~^~~
ZeroDivisionError: division by zero

 

Variadic 제너리

TypeDict를 상속받으면Java - Spring 에서의 모델이나 objectMapper.readValue 처럼, 클래스-객체의 프로퍼티에 값을 넣어준다.

class Movie(TypedDict):
   title: str
   year: NotRequired[int]

m1: Movie = {"title": "Black Panther", "year": 2018}  # OK
m2: Movie = {"title": "Star Wars"}  # OK (year is not required)
m3: Movie = {"year": 2022}  # ERROR (missing required field title)

NotRequired 설정도 가능하다

class Movie(TypedDict, total=False):
   title: Required[str]
   year: int

 

Self Return 사용

기존에는 self를 반환하면 타입 힌트를 사용하여 해당 타입을 반환할 수 있었다.

class Shape:
    def set_scale(self, scale: float) -> Shape:
        self.scale = scale
        return self

Shape().set_scale(0.5)  # => Shape

하지만 이런 경우, Circle().set_scale(0.5) 에서 Shape 형태로 반환되어, set_radius()를 호출 할 수 없게 된다.

class Circle(Shape):
    def set_radius(self, r: float) -> Circle:
        self.radius = r
        return self

Circle().set_scale(0.5)  # *Shape*, not Circle
Circle().set_scale(0.5).set_radius(2.7)
# => Error: Shape has no attribute set_radius

기존 버전에서는 아래와 같이 별도의 TShap를 사용해야 했지만

from typing import TypeVar

TShape = TypeVar("TShape", bound="Shape")

class Shape:
    def set_scale(self: TShape, scale: float) -> TShape:
        self.scale = scale
        return self


class Circle(Shape):
    def set_radius(self, radius: float) -> Circle:
        self.radius = radius
        return self

Circle().set_scale(0.5).set_radius(2.7)  # => Circle

Self 라는 직관적인 형태를 제공하여 개선하였다.

from typing import Self

class Shape:
    def set_scale(self, scale: float) -> Self:
        self.scale = scale
        return self


class Circle(Shape):
    def set_radius(self, radius: float) -> Self:
        self.radius = radius
        return self

 

사용한 코드는 모두 PEP 공식 문서를 참조했습니다.

 

블로그의 정보

PyTong

PyTong

활동하기