1. Dataclasses
dataclass는 Python 3.7에서 도입된 기능으로, 데이터를 저장하고 처리하기 위한 클래스를 효율적으로 생성할 수 있게 해주는 기능입니다. 주로 데이터 모델링에 사용되며, 반복적인 코드(보일러플레이트)를 줄여주는 역할을 합니다.
1.1 기본 사용법
일반적인 클래스와 dataclass의 차이를 비교해보겠습니다.
# 일반적인 클래스 정의
class User:
def __init__(self, id, name, email):
self.id = id
self.name = name
self.email = email
def __repr__(self):
return f"User(id={self.id}, name={self.name}, email={self.email})"
def __eq__(self, other):
if not isinstance(other, User):
return NotImplemented
return (self.id, self.name, self.email) == (other.id, other.name, other.email)
# 일반적인 클래스 정의
class User:
def __init__(self, id, name, email):
self.id = id
self.name = name
self.email = email
def __repr__(self):
return f"User(id={self.id}, name={self.name}, email={self.email})"
def __eq__(self, other):
if not isinstance(other, User):
return NotImplemented
return (self.id, self.name, self.email) == (other.id, other.name, other.email)
# dataclass를 사용한 방식
from dataclasses import dataclass
@dataclass
class User:
id: int
name: str
email: str
user = User(123, 'hojun', 'hojun@gmail.com')
print(user) # User(id=123, name='hojun', email='hojun@gmail.com')
1.2 주요 기능
1.2.1 기본값 설정
from dataclasses import dataclass
@dataclass
class Configuration:
host: str = 'localhost'
port: int = 8080
debug: bool = False
config = Configuration()
print(config) # Configuration(host='localhost', port=8080, debug=False)
1.2.2 불변 객체 생성
@dataclass(frozen=True)
class Settings:
api_key: str
timeout: int = 30
settings = Settings('my-secret-key')
print(settings) # Settings(api_key='my-secret-key', timeout=30)
# settings.api_key = 'new-key' # FrozenInstanceError 발생
1.3 고급 기능
1.3.1 필드 옵션 설정
dataclasses.field() 함수는 dataclass 필드의 동작을 세밀하게 제어할 수 있게 해주는 다양한 옵션을 제공합니다. 주요 옵션은 다음과 같습니다.
- default: 기본값 설정
- default_factory: 기본값을 동적으로 생성
- init: 생성자에 포함할지 여부
- repr: 객체를 문자열로 표현할 때 포함할지 여부
- compare: 비교 연산자 생성 여부
from dataclasses import dataclass, field
from datetime import datetime
@dataclass
class User:
id: int
name: str
email: str
active: bool = True
created_at: str = field(default_factory=lambda: datetime.now().isoformat())
_search_string: str = field(init=False, repr=False)
def __post_init__(self):
self._search_string = f"{self.name}:{self.email}".lower()
user = User(1, "Hojun", "hojun@example.com")
print(user) # created_at이 현재 시간으로 설정됨
1.3.2 상속
from datetime import datetime
@dataclass
class User:
id: int
name: str
email: str
active: bool = True
created_at: str = field(default_factory=lambda: datetime.now().isoformat())
_search_string: str = field(init=False, repr=False)
def __post_init__(self):
self._search_string = f"{self.name}:{self.email}".lower()
@dataclass
class Employee(User):
salary: float = 0.0
department: str = 'Engineering'
employee = Employee(1, "Hojun", "hojun@example.com", salary=50000)
print(employee)
1.3.3 비교 연산자 자동 생성
@dataclass(order=True)
class Number:
value: int
numbers = [Number(3), Number(1), Number(2)]
print(sorted(numbers)) # [Number(value=1), Number(value=2), Number(value=3)]