python/응용

dataclass: mutable default values

wefree 2023. 7. 9. 17:19

아래 코드에서 phone_numbers 는 모든 객체들이 공유되어, 의도하지 않는 결과가 발생시킬 수 있다. 이를 막기 위해 파이썬에서는  'ValueError: mutable default <class 'list'> for field phone_numbers is not allowed: use default_factory' 에러가 나도록 설계된 것 같다.

https://docs.python.org/3/library/dataclasses.html#mutable-default-values 참고

from dataclasses import dataclass


@dataclass
class Person:
    name: str
    phone_numbers: list[str] = []

 

에러 메시지에 나온 것 처럼 'default_factory' 를 사용하도록 한다.

import random
import string
from dataclasses import dataclass, field


def generate_id() -> str:
    return "".join(random.choices(string.ascii_letters, k=12))


@dataclass
class Person:
    name: str
    phone_numbers: list[str] = field(default_factory=list)

    # init=False: Person 객체를 만들 때, 직접 id 값을 지정해 만들 수 없다. (반드시 default_factory 이용)
    id: str = field(init=False, default_factory=generate_id)

    two_phone_number: list[str] = field(init=False)

    def __post_init__(self) -> None:
        self.two_phone_number = self.phone_numbers[:2]


Person(name='kjm')  # Person(name='kjm', phone_numbers=[], id='BgVWhDWryQRA', two_phone_number=[])
Person(name='kjm', id='abc')  # TypeError: Person.__init__() got an unexpected keyword argument 'id'
Person(name='kjm', phone_numbers=['010-123-4567']) # Person(name='kjm', phone_numbers=['010-123-4567'], id='WuuGGEPoCKnC', two_phone_number=['010-123-4567'])