dataclass
파이썬 3.7부터 dataclass 라는 모듈이 추가되었다
데이터를 담는 클래스로 활용 가능하고, import 후에 @dataclass 라는 데코레이터를 사용하면 된다
dataclass 사용법
- 자동차 정보를 담는 클래스를 예시로 기존의 클래스와 데이터클래스를 비교해보자
a. 그냥 클래스를 사용해서 자동차를 만들때
import random
import string
def generate_id() -> str:
return "".join(random.choices(string.ascii_uppercase,k=12))
class Car:
def __init__(self,brand: str, name: str) -> None:
self.brand = brand
self.name = name
def __str__(self) -> str:
return f"{self.brand} - {self.name}"
def main() -> None:
car : Car = Car(brand="HY",name="Sonata")
print(car)
b. 데이터 클래스를 사용해서 자동차를 만들 때
import random
import string
from dataclass import dataclass
def generate_id() -> str:
return "".join(random.choices(string.ascii_uppercase,k=12))
@dataclass
class Car:
name: str
brand: str
def main() -> None:
car : Car = Car(name="Sonata",brand="HY")
print(car)
한 눈에 봐도 코드의 길이가 짧아진 것을 볼 수가 있다. instance variable을 위와 같이 작성해주면 dataclass 작성이 끝난다
기존의 클래스와 비교해서 데이터 클래스가 더 빠르고 쉬운 이유는 아래와 같다
- 데이터 클래스가 이니셜라이저를 자동으로 생성
- repr 메소드도 자동으로 생성해주기에 위에서와 같이 print를 찍을 때 인스턴스의 값을 보기 위해 따로 str 메소드 선언을 해주지 않아도 된다
- 위와 같이 name: str 같은 형식으로 타입 지정을 쉽게 제공
dataclass 여러 기능
1. 디폴트 값 설정
아래와 같이 in_stock 이라는 인스턴스 변수에 boolean 값으로 True를 주면 이니셜라이저에 따로 명시하지 않아도 디폴트 값이 True로 설정된다
@dataclass
class Car:
name: str
brand: str
in_stock: True
car : Car = Car(name="Sonata",brand="HY",in_stock=True)
조금 더 심화해서, 차가 발매되는 버전들을 넣을 list와 아이디에 디폴트 값을 할당해보자
주의할 점은 versions: list = [] 와 같은 식으로 줄 수는 없다. list는 mutable하기 때문에 모든 인스턴스들이 필드의 기본 값을 공유하기 때문에 허용되지 않는다.
따라서 field를 import하고 default_factory를 사용해주어야 함. 데이터클래스가 클래스를 생성할 때, default_factory=list 로 적어놓은 함수를 call해서 매번 새로운 리스트를 생성해준다
@dataclass
class Car:
name: str
brand: str
in_stock: True
versions: list = field(default_factory=list)
id: str = field(default_factory=generate_id)
car : Car = Car(name='Sonata',brand='HY',id="my-car")
디폴트 값을 준 것이니, 당연히 클래스를 만들 때 값을 넣어주면 해당 값을 가진 객체가 생성된다
Init 옵션 주기
여기에서 위와 같이 id를 따로 생성해줄 수 없게 만들고 싶을 때는, init 옵션을 사용하자
from typing import List
@dataclass
class Car:
name: str
brand: str
in_stock: True
versions: List[str] = field(default_factory=list)
id: str = field(init=False,default_factory=generate_id)
이렇게 init=False 옵션을 주고 이니셜라이즈에 id 값을 넣어주면 아래와 같은 에러가 발생함
TypeError: __init__() got an unexpected keyword argument 'id'
dataclass 적용 예시
- 네이버 로그인 로직 구현 중 아이디와 패스워드를 담는 변수를 데이터클래스로 구현해보도록 하자.
dataset 디렉토리 하위에 data.py 파일을 만들어 아래처럼 코드를 작성해보도록 하자.
dataset/data.py
from dataclasses import dataclass
class LoginData():
_id: str
_pw: str
naver_login.py
from src.dataset.data import LoginData
class NaverLogin():
def __init__(self, login_data: LoginData, browser) -> None:
self.login_url: str = "https://nid.naver.com/nidlogin.login?mode=form&url=https%3A%2F%2Fwww.naver.com"
self.login_data = login_data
self.browser = browser
def login(self) -> None:
self.move_login_page()
self.input_id()
self.input_pw()
self.click_login_button()
def move_login_page(self) -> None:
# ...
def input_id(self) -> None:
# ...
pc.copy(self.login_data._id)
def input_pw(self) -> None:
# ...
pc.copy(self.login_data._pw)
def click_login_button(self) -> None:
# ...