What is the benefit of using dataclass on python?
생성
from dataclasses import dataclass
@dataclass
class C:
...
@dataclass()
class C:
...
@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False,
match_args=True, kw_only=False, slots=False, weakref_slot=False)
class C:
...
Python
복사
옵션 설명
•
•
repr: If true (the default), a __repr__() method will be generated. The generated repr string will have the class name and the name and repr of each field, in the order they are defined in the class. Fields that are marked as being excluded from the repr are not included. For example: InventoryItem(name='widget', unit_price=3.0, quantity_on_hand=10).
•
order: If true (the default is False), __lt__(), __le__(), __gt__(), and __ge__() methods will be generated. These compare the class as if it were a tuple of its fields, in order. Both instances in the comparison must be of the identical type. If order is true and eq is false, a ValueError is raised.
•
unsafe_hash: If False (the default), a __hash__() method is generated according to how eq and frozen are set.
__hash__() is used by built-in hash(), and when objects are added to hashed collections such as dictionaries and sets. Having a __hash__() implies that instances of the class are immutable. Mutability is a complicated property that depends on the programmer’s intent, the existence and behavior of __eq__(), and the values of the eq and frozen flags in the dataclass() decorator.
By default, dataclass() will not implicitly add a __hash__() method unless it is safe to do so. Neither will it add or change an existing explicitly defined __hash__() method. Setting the class attribute __hash__ = None has a specific meaning to Python, as described in the __hash__() documentation.
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.
Here are the rules governing implicit creation of a __hash__() method. Note that you cannot both have an explicit __hash__() method in your dataclass and set unsafe_hash=True; this will result in a TypeError.
If eq and frozen are both true, by default dataclass() will generate a __hash__() method for you. If eq is true and frozen is false, __hash__() will be set to None, marking it unhashable (which it is, since it is mutable). If eq is false, __hash__() will be left untouched meaning the __hash__() method of the superclass will be used (if the superclass is object, this means it will fall back to id-based hashing).
hash()는 내장 hash()에서 사용되며, 사전(dictionary) 및 집합(set)과 같은 해시 기반 컬렉션에 객체가 추가될 때 사용됩니다. hash()를 가지고 있다는 것은 해당 클래스의 인스턴스가 불변(immutable)임을 의미합니다. 가변성(mutability)은 프로그래머의 의도, eq()의 존재 및 동작, 그리고 dataclass() 데코레이터의 eq와 frozen 플래그 값에 따라 복잡한 속성이 됩니다.
기본적으로, dataclass()는 안전하게 hash() 메서드를 암묵적으로 추가하지 않습니다. 또한 이미 명시적으로 정의된 hash() 메서드를 추가하거나 변경하지 않습니다. 클래스 속성 hash = None을 설정하는 것은 파이썬에서 특정 의미를 가지며, hash() 설명서에 설명되어 있습니다.
만약 hash()가 명시적으로 정의되지 않았거나 None으로 설정되었다면, dataclass()는 암묵적인 hash() 메서드를 추가할 수 있습니다. 이는 권장되지는 않지만, 클래스가 논리적으로는 불변하지만 여전히 변경될 수 있는 경우에는 unsafe_hash=True로 dataclass()가 hash() 메서드를 생성하도록 강제할 수 있습니다. 이는 특수한 사용 사례로, 신중하게 고려해야 합니다.
hash() 메서드의 암묵적인 생성 규칙은 다음과 같습니다. dataclass()에서 명시적으로 정의된 hash() 메서드와 unsafe_hash=True를 동시에 사용할 수는 없으며, 이는 TypeError가 발생합니다.
eq와 frozen이 모두 True인 경우, dataclass()는 기본적으로 hash() 메서드를 생성합니다. eq가 True이고 frozen이 False인 경우, hash()는 None으로 설정되어 불가해시(unhashable)로 표시됩니다(이는 해당 객체가 가변적이기 때문입니다). eq가 False인 경우, hash()는 변경되지 않고 슈퍼클래스의 hash() 메서드가 사용됩니다(슈퍼클래스가 object인 경우, 이는 id 기반 해싱으로 되돌아갑니다).
•
frozen: If true (the default is False), assigning to fields will generate an exception. This emulates read-only frozen instances. If __setattr__() or __delattr__() is defined in the class, then TypeError is raised. See the discussion below.
•
match_args: If true (the default is True), the __match_args__ tuple will be created from the list of parameters to the generated __init__() method (even if __init__() is not generated, see above). If false, or if __match_args__ is already defined in the class, then __match_args__ will not be generated.
버전 3.10에 추가.
•
kw_only: If true (the default value is False), then all fields will be marked as keyword-only. If a field is marked as keyword-only, then the only effect is that the __init__() parameter generated from a keyword-only field must be specified with a keyword when __init__() is called. There is no effect on any other aspect of dataclasses. See the parameter glossary entry for details. Also see the KW_ONLY section.
버전 3.10에 추가.
버전 3.10에 추가.
버전 3.11에서 변경: If a field name is already included in the __slots__ of a base class, it will not be included in the generated __slots__ to prevent overriding them. Therefore, do not use __slots__ to retrieve the field names of a dataclass. Use fields() instead. To be able to determine inherited slots, base class __slots__ may be any iterable, but not an iterator.
•
weakref_slot: If true (the default is False), add a slot named “__weakref__”, which is required to make an instance weakref-able. It is an error to specify weakref_slot=True without also specifying slots=True.
상속
클래스의 모든 베이스 클래스들을 MRO 역순(즉, object 에서 시작해서)으로 조사하고, 발견되는 데이터 클래스마다 그 베이스 클래스의 필드들을 순서 있는 필드 매핑에 추가합니다. 모든 생성된 메서드들은 이 합쳐지고 계산된 순서 있는 필드 매핑을 사용합니다. 필드들이 삽입 순서이기 때문에, 파생 클래스는 베이스 클래스를 재정의합니다.
@dataclass
class Base:
x: Any = 15.0
y: int = 0
@dataclass
class C(Base):
z: int = 10
x: int = 15
=>
def __init__(self, x: int = 15, y: int = 0, z: int = 10):
Python
복사
필드의 최종 목록은 순서대로 x, y, z 입니다. x 의 최종 형은 클래스 C 에서 지정된 int 입니다.
초기화 후처리
자동 생성된 __init__() 은 __post_init__() 을 호출합니다.
__init__() 이 생성되지 않았으면, 자동으로 호출 되지 않습니다.
@dataclass
class C:
a: float
b: float
c: float = field(init=False)
def __post_init__(self):
self.c = self.a + self.b
Python
복사
초기화 전용 변수
@dataclass
class C:
i: int
j: int | None = None
database: InitVar[DatabaseType | None] = 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)
Python
복사
Field
dataclasses.field(*, default=MISSING, default_factory=MISSING, init=True, repr=True, hash=None, compare=True, metadata=None, kw_only=MISSING)
@dataclass
class C:
mylist: list[int] = field(default_factory=list)
c = C()
c.mylist += [1, 2, 3]
Python
복사
•
•
default_factory: 제공되면, 이 필드의 기본값이 필요할 때 호출되는 인자가 없는 콜러블이어야 합니다. 여러 용도 중에서도, 이것은 아래에서 논의되는 것처럼 가변 기본값을 가진 필드를 지정하는 데 사용될 수 있습니다. default 와 default_factory 를 모두 지정하는 것은 에러입니다.
•
init: If true (the default), this field is included as a parameter to the generated __init__() method.
•
repr: If true (the default), this field is included in the string returned by the generated __repr__() method.
•
hash: This can be a bool or None. If true, this field is included in the generated __hash__() method. If None (the default), use the value of compare: this would normally be the expected behavior. A field should be considered in the hash if it’s used for comparisons. Setting this value to anything other than None is discouraged.
hash=False 이지만 compare=True 로 설정하는 한 가지 가능한 이유는, 동등 비교에 포함되는 필드가 해시값을 계산하는 데 비용이 많이 들고, 형의 해시값에 이바지하는 다른 필드가 있는 경우입니다. 필드가 해시에서 제외된 경우에도 비교에는 계속 사용됩니다.
•
metadata: 매핑이나 None이 될 수 있습니다. None은 빈 딕셔너리로 취급됩니다. 이 값은 MappingProxyType() 로 감싸져서 읽기 전용으로 만들어지고, Field 객체에 노출됩니다. 데이터 클래스에서는 전혀 사용되지 않으며, 제삼자 확장 메커니즘으로 제공됩니다. 여러 제삼자는 이름 공간으로 사용할 자신만의 키를 가질 수 있습니다.
•
kw_only: If true, this field will be marked as keyword-only. This is used when the generated __init__() method’s parameters are computed.