필드
라고 부름from dataclasses import dataclass
@dataclass
class C:
a: int # 필드 1
b: int = 0 # 필드 2
@dataclass()
데코레이션만 붙이면 알아서 생성해주기 때문에 편리함class Book:
def __init__(self, name: str, weight: float, shelf_id:int = 0):
self.name = name
self.weight = weight # in grams, for calculating shipping
self.shelf_id = shelf_id
test = Book('I need Python',1.5,1267)
print(test)
>>> <__main__.Book object at 0x0000014020474DC8>
__repr__
메서드가 정의되지 않았기 때문에 인스턴스를 실행하면 Book
클래스의 메모리 값이 나온다.
class Book:
def __init__(self, name: str, weight: float, shelf_id:int = 0):
self.name = name
self.weight = weight # in grams, for calculating shipping
self.shelf_id = shelf_id
def __repr__(self):
return (f"Book(name={self.name!r},weight = {self.weight!r}, shelf_id = {self.shelf_id!r})")
test = Book('I need Python',1.5,1267)
print(test)
>>> Book(name='I need Python',weight = 1.5, shelf_id = 1267)
__repr__
메서드를 정의하고 인스턴스를 실행하면 정의된 파라미터 값들을 확인할 수 있다.
하지만 매번 사용하는 모든 클래스에 매직 메서드를 정의하는 것은 귀찮고 오타로 인한 에러 발생의 위험이 있다. 그렇기 때문에 데이터 클래스라는 데코레이터를 통해 간단히 매직 메서드를 정의할 수 있다.
from dataclasses import dataclass
@dataclass
class Book:
name: str
weight: float
shelf_id: int = 0
test = Book('I need Python',1.5,1267)
print(test)
>>> Book(name='I need Python', weight=1.5, shelf_id=1267)
굉장히 코드가 간결해진것을 볼 수 있다. 참고로 init
메서드 또한, 데이터 클래스에서 자동으로 생성해주기 때문에 따로 정의하지 않아도 아래와 같이 정상적으로 실행된다.
# no dataclass
class Number:
__init__(self, val):
self.val = val
>>> one = Number(1)
>>> one.val
>>> 1
# use dataclass
@dataclass
class Number:
val:int
>>> one = Number(1)
>>> one.val
>>> 1
만약 dataclass
를 사용하며 init
을 사용하고 싶으면 __post_init__
을 사용하면 된다. 기능은 init
과 동일하며 단지, dataclass
에서 자동으로 생성한 init
이 __post_init__
을 호출해준다.
import math
@dataclass
class FloatNumber:
val: float = 0.0
def __post_init__(self):
self.decimal, self.integer = math.modf(self.val)
>>> a = Number(2.2)
>>> a.val
>>> 2.2
>>> a.integer
>>> 2.0
>>> a.decimal
>>> 0.2
init
True
가 기본 값True
면 __init__
메서드가 생성됨__init__
메서드를 정의 했으면 이 매개변수는 무시됨repr
True
가 기본 값True
면 __repr__
메서드가 생성됨__repr__
메서드는 해당 객체가 어떤 객체인지 표현하는 문자열을 반환함__repr__
메서드를 정의 했으면 이 매개변수는 무시됨eq
True
가 기본 값True
면 __eq__
메서드가 생성됨__eq__
메서드는 두 객체가 동일한지 판단해주는 연산 메서드__eq__
메서드를 정의 했으면 이 매개변수는 무시됨order
False
가 기본 값True
면 __lt__
, __le__
, __gt__
, __ge__
메서드가 생성됨eq
와 달리 객체의 대소를 판단할 때 사용sorted
를 사용할 수 있어짐 __lt__
, __le__
, __gt__
, __ge__
메서드를 정의 했으면 이 매개변수는 무시됨from dataclasses import dataclass
@dataclass(order=True)
class Book:
name: str
weight: float
shelf_id: int
b1 = Book('I need Python',1.5,1267)
b2 = Book('You need Python',0.5,6453)
print(b1>b2)
>>> False # 'I' < 'Y'
frozen
False
가 기본 값True
면 필드에 새로운 값을 대입하려고 하면 예외를 발생시킴from dataclasses import dataclass
@dataclass(frozen=True)
class Book:
name: str
weight: float
shelf_id: int = 0
test = Book('I need Python',1.5,1267)
test.weight = 2.43
print(test)
>>> Traceback (most recent call last):
File line 11, in <module>
test.weight = 2.43
File "<string>", line 4, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'weight'
unsafe_hash
False
가 기본 값eq
와 frozen
의 설정에 따라 __hash__
메서드가 생성됨__hash__
메서드는 딕셔너리, 집합과 같은 해시 컬렉션에 객체가 추가될 때 사용from dataclasses import dataclass
@dataclass(unsafe_hash=True)
class Book:
name: str
weight: float
shelf_id: int
b1 = Book('I need Python',1.5,1267)
b2 = Book('You need Python',0.5,6453)
b3 = Book('I need Python',1.5,1267)
b4 = Book('You need Python',0.5,6453)
print(set([b1,b2,b3,b4]))
>>> {Book(name='I need Python', weight=1.5, shelf_id=1267), Book(name='You need Python', weight=0.5, shelf_id=6453)}
filed
라는 특별한 함수를 사용해 기본 값을 설정해야 함filed
함수의 default
, default_factory
옵션에 기본 값으로 설정할 값을 넣으면 됨from dataclasses import dataclass, field
from typing import List
@dataclass
class Book:
name: str
weight: float
shelf_id: int
subject: str = field(default='IT')
author: List[str] = field(default_factory=list)
b1 = Book('I need Python',1.5,1267)
print(b1)
>>> Book(name='I need Python', weight=1.5, shelf_id=1267, subject='IT', author=[])
마지막에 filed 오타났어요~