# `dataclasses` — 데이터 클래스

소스 코드: Lib/dataclasses.py

이 모듈은 `__init__()` 나 `__repr__()` 과 같은 생성된 특수 메서드 를 사용자 정의 클래스에 자동으로 추가하는 데코레이터와 함수를 제공합니다. 원래 PEP 557 에 설명되어 있습니다.

생성된 메서드에서 사용할 멤버 변수는 PEP 526 형 어노테이션을 사용하여 정의됩니다. 예를 들어, 이 코드는:

    from dataclasses import dataclass

    @dataclass
    class InventoryItem:
        """Class for keeping track of an item in inventory."""
        name: str
        unit_price: float
        quantity_on_hand: int = 0

        def total_cost(self) -> float:
            return self.unit_price * self.quantity_on_hand

다른 것 중에서도, 다음과 같은 `__init__()` 를 추가합니다:

    def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0):
        self.name = name
        self.unit_price = unit_price
        self.quantity_on_hand = quantity_on_hand

이 메서드는 클래스에 자동으로 추가됩니다: 위의 `InventoryItem` 정의에서 직접 지정되지는 않았습니다.

버전 3.7에 추가.

## 모듈 수준의 데코레이터, 클래스 및 함수

`@``dataclasses.``dataclass`(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)

  이 함수는 (아래에서 설명하는) 생성된 특수 메서드를 클래스에 추가하는데 사용되는 데코레이터 입니다.

  `dataclass()` 데코레이터는 클래스를 검사하여 필드를 찾습니다. 필드는 형 어노테이션을 가진 클래스 변수로 정의됩니다. 아래에 설명된 두 가지 예외를 제외하고는, `dataclass()` 는 변수 어노테이션에 지정된 형을 검사하지 않습니다.

  생성된 모든 메서드의 필드 순서는 클래스 정의에 나타나는 순서입니다.

  `dataclass()` 데코레이터는 여러 《던더(dunder)》 메서드들을 클래스에 추가하는데, 아래에서 설명합니다. 추가할 메서드가 클래스에 이미 존재하면, 동작은 아래에 설명된 대로 매개변수에 따라 다릅니다. 데코레이터는 호출된 클래스와 같은 클래스를 반환합니다; 새 클래스가 만들어지지 않습니다.

  `dataclass()` 가 매개변수 없는 단순한 데코레이터로 사용되면, 이 서명에 문서화 된 기본값들이 제공된 것처럼 행동합니다. 즉, 다음 `dataclass()` 의 세 가지 용법은 동등합니다:

      @dataclass
      class C:
          ...

      @dataclass()
      class C:
          ...

      @dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
      class C:
         ...

  `dataclass()` 의 매개변수는 다음과 같습니다:

  - `init`: 참(기본값)이면, `__init__()` 메서드가 생성됩니다.

    클래스가 이미 `__init__()` 를 정의했으면, 이 매개변수는 무시됩니다.

  - `repr`: 참(기본값)이면, `__repr__()` 메서드가 생성됩니다. 생성된 repr 문자열은 클래스 이름과 각 필드의 이름과 repr 을 갖습니다. 각 필드는 클래스에 정의된 순서대로 표시됩니다. repr에서 제외하도록 표시된 필드는 포함되지 않습니다. 예를 들어: 예 :`InventoryItem(name='widget', unit_price=3.0, quantity_on_hand=10)`.

    클래스가 이미 `__repr__()` 을 정의했으면, 이 매개변수는 무시됩니다.

  - `eq`: 참(기본값)이면, `__eq__()` 메서드가 생성됩니다. 이 메서드는 클래스를 필드의 튜플인 것처럼 순서대로 비교합니다. 비교되는 두 인스턴스는 같은 형이어야 합니다.

    클래스가 이미 `__eq__()` 를 정의했으면, 이 매개변수는 무시됩니다.

  - `order`: 참이면 (기본값은 `False`), `__lt__()`, `__le__()`, `__gt__()`, `__ge__()` 메서드가 생성됩니다. 이것들은 클래스를 필드의 튜플인 것처럼 순서대로 비교합니다. 비교되는 두 인스턴스는 같은 형이어야 합니다. `order` 가 참이고 `eq` 가 거짓이면 `ValueError` 가 발생합니다.

    클래스가 이미 `__lt__()`, `__le__()`, `__gt__()`, `__ge__()` 중 하나를 정의하고 있다면 `TypeError` 가 발생합니다.

  - `unsafe_hash`: `False` (기본값) 면 : `eq` 와 `frozen` 의 설정에 따라 `__hash__()` 메서드가 생성됩니다.

    `__hash__()` 는 내장 `hash()` 에 의해 사용되며, 딕셔너리와 집합 같은 해시 컬렉션에 객체가 추가될 때 사용됩니다. `__hash__()` 를 갖는다는 것은 클래스의 인스턴스가 불변이라는 것을 의미합니다. 가변성은 프로그래머의 의도, `__eq__()` 의 존재와 행동, `dataclass()` 데코레이터의 `eq` 와 `frozen` 플래그의 값에 의존하는 복잡한 성질입니다.

    기본적으로, `dataclass()` 는 안전하지 않다면 `__hash__()` 메서드를 묵시적으로 추가하지 않습니다. 기존에 명시적으로 정의된 `__hash__()` 메서드를 추가하거나 변경하지도 않습니다. `__hash__()` 문서에서 설명된 대로, 클래스 어트리뷰트를 `__hash__ = None` 로 설정하는 것은 파이썬에 특별한 의미가 있습니다.

    If `__hash__()` is not explicitly defined, or if it is set to `None`, then `dataclass()` may add an implicit `__hash__()` method. Although not recommended, you can force `dataclass()` to create a `__hash__()` method with `unsafe_hash=True`. This might be the case if your class is logically immutable but can nonetheless be mutated. This is a specialized use case and should be considered carefully.

    다음은 `__hash__()` 메서드의 묵시적 생성을 관장하는 규칙입니다. 데이터 클래스에 명시적 `__hash__()` 메서드를 가지면서 `unsafe_hash=True` 를 설정할 수는 없습니다; 그러면 `TypeError` 가 발생합니다.

    `eq` 와 `frozen` 이 모두 참이면, 기본적으로 `dataclass()` 는 `__hash__()` 메서드를 만듭니다. `eq` 가 참이고 `frozen` 이 거짓이면, `__hash__()` 가 `None` 으로 설정되어 해시 불가능하다고 표시됩니다(가변이기 때문입니다). 만약 `eq` 가 거짓이면, `__hash__()` 를 건드리지 않는데, 슈퍼 클래스의 `__hash__()` 가 사용된다는 뜻이 됩니다 (슈퍼 클래스가 `object` 라면, id 기반 해싱으로 돌아간다는 뜻입니다).

  - `frozen`: 참이면 (기본값은 `False`), 필드에 대입하면 예외를 발생시킵니다. 이것은 읽기 전용 고정 인스턴스를 흉내 냅니다. `__setattr__()` 또는 `__delattr__()` 이 클래스에 정의되어 있다면 `TypeError` 가 발생합니다. 아래 토론을 참조하십시오.

  필드는 선택적으로 일반적인 파이썬 문법을 사용하여 기본값을 지정할 수 있습니다:

      @dataclass
      class C:
          a: int       # 'a' has no default value
          b: int = 0   # assign a default value for 'b'

  이 예제에서, `a` 와 `b` 모두 추가된 `__init__()` 메서드에 포함되는데, 이런 식으로 정의됩니다:

      def __init__(self, a: int, b: int = 0):

  기본값이 없는 필드가 기본값이 있는 필드 뒤에 오는 경우 `TypeError` 가 발생합니다. 이것은 단일 클래스에서 일어날 수도 있고, 클래스 상속의 결과일 때도 마찬가지입니다.

`dataclasses.``field`(*, default=MISSING, default_factory=MISSING, repr=True, hash=None, init=True, compare=True, metadata=None)

  일반적이고 간단한 사용 사례의 경우 다른 기능은 필요하지 않습니다. 그러나 필드별로 추가 정보가 필요한 일부 데이터 클래스 기능이 있습니다. 추가 정보에 대한 필요성을 충족시키기 위해, 기본 필드 값을 제공된 `field()` 함수 호출로 바꿀 수 있습니다. 예를 들면:

      @dataclass
      class C:
          mylist: List[int] = field(default_factory=list)

      c = C()
      c.mylist += [1, 2, 3]

  위에서 보인 것처럼, `MISSING` 값은 `default` 와 `default_factory` 매개변수가 제공되는지를 탐지하는데 사용되는 표지 객체입니다. `None` 이 `default` 에 유효한 값이기 때문에 이 표지가 사용됩니다. 어떤 코드도 `MISSING` 값을 직접 사용해서는 안 됩니다.

  `field()` 의 매개변수는 다음과 같습니다:

  - `default`: 제공되면, 이 필드의 기본값이 됩니다. 이것은 `field()` 호출 자체가 기본값의 정상 위치를 대체하기 때문에 필요합니다.

  - `default_factory`: 제공되면, 이 필드의 기본값이 필요할 때 호출되는 인자가 없는 콜러블이어야 합니다. 여러 용도 중에서도, 이것은 아래에서 논의되는 것처럼 가변 기본값을 가진 필드를 지정하는 데 사용될 수 있습니다. `default` 와 `default_factory` 를 모두 지정하는 것은 에러입니다.

  - `init`: 참(기본값)이면, 이 필드는 생성된 `__init__()` 메서드의 매개변수로 포함됩니다.

  - `repr`: 참(기본값)이면, 이 필드는 생성된 `__repr__()` 메서드가 돌려주는 문자열에 포함됩니다.

  - `compare`: 참(기본값)이면, 이 필드는 생성된 같음 및 비교 메서드(`__eq__()`, `__gt__()` 등)에 포함됩니다.

  - `hash`: 이것은 bool 또는 `None` 일 수 있습니다. 참이면, 이 필드는 생성된 `__hash__()` 메서드에 포함됩니다. `None` (기본값) 이면, `compare` 의 값을 사용합니다. 이것은 일반적으로 기대되는 행동입니다. 필드가 비교에 사용되면 해시에서 고려해야 합니다. 이 값을 `None` 이외의 값으로 설정하는 것은 권장하지 않습니다.

    `hash=False` 이지만 `compare=True` 로 설정하는 한 가지 가능한 이유는, 동등 비교에 포함되는 필드가 해시값을 계산하는 데 비용이 많이 들고, 형의 해시값에 이바지하는 다른 필드가 있는 경우입니다. 필드가 해시에서 제외된 경우에도 비교에는 계속 사용됩니다.

  - `metadata`: 매핑이나 None이 될 수 있습니다. None은 빈 딕셔너리로 취급됩니다. 이 값은 `MappingProxyType()` 로 감싸져서 읽기 전용으로 만들어지고, `Field` 객체에 노출됩니다. 데이터 클래스에서는 전혀 사용되지 않으며, 제삼자 확장 메커니즘으로 제공됩니다. 여러 제삼자는 이름 공간으로 사용할 자신만의 키를 가질 수 있습니다.

  필드의 기본값이 `field()` 호출로 지정되면, 이 필드의 클래스 어트리뷰트는 지정한 `default` 값으로 대체됩니다. `default` 가 제공되지 않으면 클래스 어트리뷰트는 삭제됩니다. 그 의도는, `dataclass()` 데코레이터 실행 후에, 기본값 자체가 지정된 것처럼 클래스 어트리뷰트가 모드 필드의 기본값을 갖도록 만드는 것입니다. 예를 들어, 이렇게 한 후에는:

      @dataclass
      class C:
          x: int
          y: int = field(repr=False)
          z: int = field(repr=False, default=10)
          t: int = 20

  클래스 어트리뷰트 `C.z` 는 `10` 이 되고, 클래스 어트리뷰트 `C.t` 는 `20` 이 되고, 클래스 어트리뷰트 `C.x` 와 `C.y` 는 설정되지 않게 됩니다.

class `dataclasses.``Field`

  `Field` 객체는 정의된 각 필드를 설명합니다. 이 객체는 내부적으로 생성되며 `fields()` 모듈 수준 메서드(아래 참조)가 돌려줍니다. 사용자는 직접 `Field` 인스턴스 객체를 만들어서는 안 됩니다. 문서화 된 어트리뷰트는 다음과 같습니다:

  > - `name`: 필드의 이름.

  > - `type`: 필드의 형.

  > - `default`, `default_factory`, `init`, `repr`, `hash`, `compare`, `metadata` 는 `field()` 선언에서와 같은 의미와 값을 가지고 있습니다.

  다른 어트리뷰트도 있을 수 있지만, 내부적인 것이므로 검사하거나 의존해서는 안 됩니다.

`dataclasses.``fields`(class_or_instance)

  데이터 클래스의 필드들을 정의하는 `Field` 객체들의 튜플을 돌려줍니다. 데이터 클래스나 데이터 클래스의 인스턴스를 받아들입니다. 데이터 클래스 나 데이터 클래스의 인스턴스를 전달하지 않으면 `TypeError` 를 돌려줍니다. `ClassVar` 또는 `InitVar` 인 의사 필드는 반환하지 않습니다.

`dataclasses.``asdict`(instance, *, dict_factory=dict)

  데이터 클래스 `instance` 를 딕셔너리로 변환합니다 (팩토리 함수 `dict_factory` 를 사용합니다). 각 데이터 클래스는 각 필드를 `name: value` 쌍으로 갖는 딕셔너리로 변환됩니다. 데이터 클래스, 딕셔너리, 리스트 및 튜플은 재귀적으로 변환됩니다. 예를 들면:

      @dataclass
      class Point:
           x: int
           y: int

      @dataclass
      class C:
           mylist: List[Point]

      p = Point(10, 20)
      assert asdict(p) == {'x': 10, 'y': 20}

      c = C([Point(0, 0), Point(10, 4)])
      assert asdict(c) == {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]}

  `instance` 가 데이터 클래스 인스턴스가 아닌 경우 `TypeError` 를 일으킵니다.

`dataclasses.``astuple`(instance, *, tuple_factory=tuple)

  데이터 클래스 `instance` 를 튜플로 변환합니다 (팩토리 함수 `tuple_factory` 를 사용합니다). 각 데이터 클래스는 각 필드 값들의 튜플로 변환됩니다. 데이터 클래스, 딕셔너리, 리스트 및 튜플은 재귀적으로 변환됩니다.

  이전 예에서 계속하면:

      assert astuple(p) == (10, 20)
      assert astuple(c) == ([(0, 0), (10, 4)],)

  `instance` 가 데이터 클래스 인스턴스가 아닌 경우 `TypeError` 를 일으킵니다.

`dataclasses.``make_dataclass`(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)

  새로운 데이터 클래스를 만드는데, 이름은 `cls_name` 이고, `fields` 에 정의된 필드들을 갖고, `bases` 에 주어진 베이스 클래스들을 갖고, `namespace` 로 주어진 이름 공간으로 초기화됩니다. `fields` 는 요소가 `name`, `(name, type)` 또는 `(name, type, Field)` 인 이터러블입니다. `name` 만 제공되면 `typing.Any` 가 `type` 으로 사용됩니다. `init`, `repr`, `eq`, `order`, `unsafe_hash`, `frozen` 의 값은 `dataclass()` 에서와 같은 의미가 있습니다.

  이 함수가 꼭 필요하지는 않습니다. 임의의 파이썬 메커니즘으로 `__annotations__` 을 갖는 새 클래스를 만든 후에 `dataclass()` 함수를 적용하면 데이터 클래스로 변환되기 때문입니다. 이 함수는 편의상 제공됩니다. 예를 들어:

      C = make_dataclass('C',
                         [('x', int),
                           'y',
                          ('z', int, field(default=5))],
                         namespace={'add_one': lambda self: self.x + 1})

  는 다음과 동등합니다:

      @dataclass
      class C:
          x: int
          y: 'typing.Any'
          z: int = 5

          def add_one(self):
              return self.x + 1

`dataclasses.``replace`(instance, **changes)

  `instance` 와 같은 형의 새 객체를 만드는데, 필드를 `changes` 의 값들로 대체합니다. `instance` 가 데이터 클래스가 아니라면 `TypeError` 를 발생시킵니다. `changes` 의 값이 필드를 지정하지 않으면 `TypeError` 를 발생시킵니다.

  새로 반환된 객체는 데이터 클래스의 `__init__()` 메서드를 호출하여 생성됩니다. 이렇게 함으로써 (있는 경우) `__post_init__()` 의 호출을 보장합니다.

  기본값을 가지지 않는 초기화 전용 변수가 존재한다면, `replace()` 호출에 반드시 지정해서 `__init__()` 와 `__post_init__()` 에 전달 될 수 있도록 해야 합니다.

  `changes` 가 `init=False` 를 갖는 것으로 정의된 필드를 포함하는 것은 에러입니다. 이 경우 `ValueError` 가 발생합니다.

  `replace()`를 호출하는 동안 `init=False` 필드가 어떻게 작동하는지 미리 경고합니다. 그것들은 소스 객체로부터 복사되는 것이 아니라, (초기화되기는 한다면) `__post_init__()` 에서 초기화됩니다. `init=False` 필드는 거의 사용되지 않으리라고 예상합니다. 사용된다면, 대체 클래스 생성자를 사용하거나, 인스턴스 복사를 처리하는 사용자 정의 `replace()` (또는 비슷하게 이름 지어진) 메서드를 사용하는 것이 좋을 것입니다.

`dataclasses.``is_dataclass`(class_or_instance)

  매개변수가 데이터 클래스나 데이터 클래스의 인스턴스면 `True`를 반환하고, 그렇지 않으면 `False`를 반환합니다.

  (데이터 클래스 자체가 아니라) 데이터 클래스의 인스턴스인지 알아야 한다면 `not isinstance(obj, type)` 검사를 추가하십시오:

      def is_dataclass_instance(obj):
          return is_dataclass(obj) and not isinstance(obj, type)

## 초기화 후처리

클래스에 `__post_init__()` 가 정의된 경우, 생성된 `__init__()` 코드는 `__post_init__()` 메서드를 호출합니다. 일반적으로 `self.__post_init__()` 로 호출됩니다. 그러나, `InitVar` 필드가 정의되어 있으면, 클래스에 정의된 순서대로 `__post_init__()` 로 전달됩니다. `__init__()` 메서드가 생성되지 않으면, `__post_init__()` 가 자동으로 호출되지 않습니다.

다른 용도 중에서도, 하나나 그 이상의 다른 필드에 의존하는 필드 값을 초기화하는데 사용할 수 있습니다. 예를 들면:

    @dataclass
    class C:
        a: float
        b: float
        c: float = field(init=False)

        def __post_init__(self):
            self.c = self.a + self.b

매개변수를 `__post_init__()` 에 전달하는 방법은 초기화 전용 변수에 대한 아래 섹션을 참조하십시오. 또한 `replace()` 가 `init=False` 필드를 처리하는 방식에 관한 경고를 보십시오.

## 클래스 변수

`dataclass()` 가 실제로 필드의 형을 검사하는 두 곳 중 하나는 필드가 PEP 526 에 정의된 클래스 변수인지를 확인하는 것입니다. 필드의 형이 `typing.ClassVar` 인지 검사합니다. 필드가 `ClassVar` 인 경우, 필드로 취급되지 않고 데이터 클래스 메커니즘에서 무시됩니다. 이런 `ClassVar` 의사 필드는 모듈 수준 `fields()` 함수에 의해 반환되지 않습니다.

## 초기화 전용 변수

`dataclass()` 가 형 어노테이션을 검사하는 다른 한 곳은 필드가 초기화 전용 변수인지 확인하는 것입니다. 필드의 형이 `dataclasses.InitVar` 인지 검사합니다. 필드가 `InitVar` 인 경우, 초기화 전용 변수라고 불리는 의사 필드로 간주합니다. 실제 필드가 아니므로, 모듈 수준 `fields()` 함수에 의해 반환되지 않습니다. 초기화 전용 필드는 생성된 `__init__()` 메서드의 매개변수로 추가되며, 선택적인 `__post_init__()` 메서드로 전달됩니다. 이 외에 데이터 클래스에서 사용되는 곳은 없습니다.

예를 들어, 클래스를 만들 때 값이 제공되지 않으면, 필드가 데이터베이스로부터 초기화된다고 가정합시다:

    @dataclass
    class C:
        i: int
        j: int = None
        database: InitVar[DatabaseType] = None

        def __post_init__(self, database):
            if self.j is None and database is not None:
                self.j = database.lookup('j')

    c = C(10, database=my_database)

이 경우, `fields()` 는 `i` 와 `j` 를 위한 `Field` 객체를 반환하지만, `database` 는 반환하지 않습니다.

## 고정 인스턴스

정말로 불변인 파이썬 객체를 만드는 것은 불가능합니다. 그러나, `frozen=True` 를 `dataclass()` 데코레이터에 전달함으로써 불변성을 흉내 낼 수 있습니다. 이 경우, 데이터 클래스는 `__setattr__()` 과 `__delattr__()` 메서드를 클래스에 추가합니다. 이 메서드는 호출될 때 `FrozenInstanceError` 를 발생시킵니다.

`frozen=True` 를 사용할 때 약간의 성능 저하가 있습니다: `__init__()` 는 필드를 초기화하는데 간단한 대입을 사용할 수 없고, `object.__setattr__()` 을 사용해야 합니다.

## 계승

데이터 클래스가 `dataclass()` 데코레이터에 의해 생성될 때, 클래스의 모든 베이스 클래스들을 MRO 역순(즉, `object` 에서 시작해서)으로 조사하고, 발견되는 데이터 클래스마다 그 베이스 클래스의 필드들을 순서 있는 필드 매핑에 추가합니다. 모든 생성된 메서드들은 이 합쳐지고 계산된 순서 있는 필드 매핑을 사용합니다. 필드들이 삽입 순서이기 때문에, 파생 클래스는 베이스 클래스를 재정의합니다. 예:

    @dataclass
    class Base:
        x: Any = 15.0
        y: int = 0

    @dataclass
    class C(Base):
        z: int = 10
        x: int = 15

필드의 최종 목록은 순서대로 `x`, `y`, `z` 입니다. `x` 의 최종 형은 클래스 `C` 에서 지정된 `int` 입니다.

생성된 `C` 의 `__init__()` 메서드는 이렇게 됩니다:

    def __init__(self, x: int = 15, y: int = 0, z: int = 10):

## 기본 팩토리 함수

> `field()` 가 `default_factory` 를 지정하면, 필드의 기본값이 필요할 때 인자 없이 호출됩니다. 예를 들어, 리스트의 새 인스턴스를 만들려면, 이렇게 하세요:

>     mylist: list = field(default_factory=list)

> 필드가 (`init=False` 를 사용해서) `__init__()` 에서 제외되고, 그 필드가 `default_factory` 를 지정하면, 생성된 `__init__()` 함수는 항상 기본 팩토리 함수를 호출합니다. 이는 필드에 초기화 값을 제공할 수 있는 다른 방법이 없기 때문입니다.

## 가변 기본값

> 파이썬은 기본 멤버 변숫값을 클래스 어트리뷰트에 저장합니다. 데이터 클래스를 사용하지 않는 이 예제를 생각해보세요:

>     class C:
>         x = []
>         def add(self, element):
>             self.x.append(element)

>     o1 = C()
>     o2 = C()
>     o1.add(1)
>     o2.add(2)
>     assert o1.x == [1, 2]
>     assert o1.x is o2.x

> 클래스 `C` 의 두 인스턴스는 예상대로 같은 클래스 변수 `x` 를 공유합니다.

> 데이터 클래스를 사용해서, 만약 이 코드가 올바르다면:

>     @dataclass
>     class D:
>         x: List = []
>         def add(self, element):
>             self.x += element

> 비슷한 코드를 생성합니다:

>     class D:
>         x = []
>         def __init__(self, x=x):
>             self.x = x
>         def add(self, element):
>             self.x += element

>     assert D().x is D().x

> 이것은 클래스 `C` 를 사용한 원래 예제와 같은 문제를 가지고 있습니다. 즉, 클래스 인스턴스를 만들 때 `x` 에 대한 값을 지정하지 않는 클래스 `D` 의 두 인스턴스는 같은 `x` 를 공유합니다. 데이터 클래스는 일반적인 파이썬 클래스 생성을 사용하기 때문에, 이 동작 역시 공유합니다. 데이터 클래스가 이 조건을 감지하는 일반적인 방법은 없습니다. 대신, 데이터 클래스는 `list`, `dict`, `set` 형의 기본 매개변수를 탐지하면 `TypeError` 를 발생시킵니다. 이것은 부분적인 해결책이지만, 흔한 오류로부터 보호합니다.

> 기본 팩토리 함수를 사용하면 필드의 기본값으로 가변형의 새 인스턴스를 만들 수 있습니다:

>     @dataclass
>     class D:
>         x: list = field(default_factory=list)

>     assert D().x is not D().x

## 예외

exception `dataclasses.``FrozenInstanceError`

  Raised when an implicitly defined `__setattr__()` or `__delattr__()` is called on a dataclass which was defined with `frozen=True`. It is a subclass of `AttributeError`.