Nice programing

데이터 클래스는 무엇이며 공통 클래스와 어떻게 다릅니 까?

nicepro 2020. 11. 1. 18:39
반응형

데이터 클래스는 무엇이며 공통 클래스와 어떻게 다릅니 까?


PEP 557을 사용하면 데이터 클래스가 Python 표준 라이브러리에 도입됩니다.

그들은 @dataclass데코레이터를 사용하고 "기본값으로 변경 가능한 네임 튜플"이어야하지만 이것이 실제로 의미하는 바가 무엇인지, 그리고 그것들이 일반적인 클래스와 어떻게 다른지 잘 모르겠습니다.

파이썬 데이터 클래스는 정확히 무엇이며 언제 사용하는 것이 가장 좋습니까?


데이터 클래스는 많은 논리를 포함하는 것 이상으로 상태를 저장하도록 설계된 정규 클래스입니다. 대부분 속성으로 구성된 클래스를 만들 때마다 데이터 클래스를 만들었습니다.

어떤 dataclasses모듈이하는 것은 만들 것입니다 쉽게 데이터 클래스를 만들 수 있습니다. 그것은 당신을 위해 많은 보일러 플레이트를 처리합니다.

이것은 데이터 클래스가 해시 가능해야 할 때 특히 중요합니다. 이를 위해서는 __hash__방법과 방법 이 필요합니다 __eq__. __repr__디버깅을 쉽게하기 위해 사용자 지정 메서드를 추가하면 매우 장황해질 수 있습니다.

class InventoryItem:
    '''Class for keeping track of an item in inventory.'''
    name: str
    unit_price: float
    quantity_on_hand: int = 0

    def __init__(
            self, 
            name: str, 
            unit_price: float,
            quantity_on_hand: int = 0
        ) -> None:
        self.name = name
        self.unit_price = unit_price
        self.quantity_on_hand = quantity_on_hand

    def total_cost(self) -> float:
        return self.unit_price * self.quantity_on_hand

    def __repr__(self) -> str:
        return (
            'InventoryItem('
            f'name={self.name!r}, unit_price={self.unit_price!r}, '
            f'quantity_on_hand={self.quantity_on_hand!r})'

    def __hash__(self) -> int:
        return hash((self.name, self.unit_price, self.quantity_on_hand))

    def __eq__(self, other) -> bool:
        if not isinstance(other, InventoryItem):
            return NotImplemented
        return (
            (self.name, self.unit_price, self.quantity_on_hand) == 
            (other.name, other.unit_price, other.quantity_on_hand))

다음과 dataclasses같이 줄일 수 있습니다.

from dataclasses import dataclass

@dataclass(unsafe_hash=True)
class InventoryItem:
    '''Class for keeping track of an item in inventory.'''
    name: str
    unit_price: float
    quantity_on_hand: int = 0

    def total_cost(self) -> float:
        return self.unit_price * self.quantity_on_hand

동일한 클래스의 장식은 비교 방법 (발생 수 __lt__, __gt__등) 및 핸들 불변성.

namedtuple클래스도 데이터 클래스이지만 기본적으로 변경할 수 없습니다 (시퀀스 일뿐만 아니라). dataclasses이 점에서 훨씬 더 유연 하며 namedtuple클래스 와 동일한 역할을 수행 할 수 있도록 쉽게 구성 할 수 있습니다 .

PEP는 attrs프로젝트 에서 영감을 얻어 더 많은 작업을 수행 할 수 있습니다 (슬롯, 유효성 검사기, 변환기, 메타 데이터 등 포함).

몇 가지 예를 보려면 최근 dataclasses에 여러 Advent of Code 솔루션을 사용 했습니다. 7 일 , 8 일 , 11 일20 의 솔루션을 참조하십시오 .

dataclassesPython 버전 3.7 미만에서 모듈 을 사용 하려면 백 포트 된 모듈 (3.6 필요)을 설치하거나 attrs위에서 언급 한 프로젝트를 사용할 수 있습니다 .


개요

문제가 해결되었습니다. 그러나이 답변은 데이터 클래스의 기본 이해를 돕기 위해 몇 가지 실용적인 예를 추가합니다.

파이썬 데이터 클래스는 정확히 무엇이며 언제 사용하는 것이 가장 좋습니까?

  1. 코드 생성기 : 상용구 코드 생성; 일반 클래스에서 특수 메서드를 구현하거나 데이터 클래스에서 자동으로 구현하도록 선택할 수 있습니다.
  2. 데이터 컨테이너 : 구조 그러한 자주 점, 속성 액세스 할 수있는 데이터를 보유 (예를 들어, 튜플 및 dicts), 클래스, namedtuple및 다른 사람 .

"기본값으로 변경 가능한 namedtuples"

후자의 의미는 다음과 같습니다.

  • mutable : 기본적으로 데이터 클래스 속성을 다시 할당 할 수 있습니다. 선택적으로 불변으로 만들 수 있습니다 (아래 예제 참조).
  • namedtuple : namedtuple또는 일반 클래스 와 같은 점선, 속성 액세스가 있습니다 .
  • default : 속성에 기본값을 할당 할 수 있습니다.

일반적인 클래스와 비교할 때 주로 상용구 코드를 입력하는 데 드는 비용이 절감됩니다.


풍모

다음은 데이터 클래스 기능에 대한 개요입니다 (요약 테이블의 예 참조).

당신이 얻는 것

다음은 데이터 클래스에서 기본적으로 얻는 기능입니다.

속성 + 표현 + 비교

import dataclasses


@dataclasses.dataclass
#@dataclasses.dataclass()                                       # alternative
class Color:
    r : int = 0
    g : int = 0
    b : int = 0

다음 기본값은 자동으로 설정됩니다 True.

@dataclasses.dataclass(init=True, repr=True, eq=True)

켤 수있는 항목

적절한 키워드가로 설정된 경우 추가 기능을 사용할 수 있습니다 True.

주문

@dataclasses.dataclass(order=True)
class Color:
    r : int = 0
    g : int = 0
    b : int = 0

이제 더 강력한 동등성 테스트와 < > <= >=유사하게 순서 지정 방법이 구현되었습니다 (연산자 오버로딩 functools.total_ordering:).

해시 가능, 변경 가능

@dataclasses.dataclass(unsafe_hash=True)                        # override base `__hash__`
class Color:
    ...

객체는 잠재적으로 변경 가능하지만 (원하지 않을 수 있음) 해시가 구현됩니다.

해시 가능, 불변

@dataclasses.dataclass(frozen=True)                                 # `eq=True` (default) to be immutable 
class Color:
    ...

이제 해시가 구현되었으며 개체를 변경하거나 속성에 할당 할 수 없습니다.

전반적으로 객체는 unsafe_hash=True또는 인 경우 해시 가능합니다 frozen=True.

자세한 내용은 원래 해싱 논리 테이블 을 참조하십시오.

당신이 얻지 못하는 것

다음 기능을 얻으려면 특수 방법을 수동으로 구현해야합니다.

포장 풀기

@dataclasses.dataclass
class Color:
    r : int = 0
    g : int = 0
    b : int = 0

    def __iter__(self):
        yield from dataclasses.astuple(self)

최적화

@dataclasses.dataclass
class SlottedColor:
    __slots__ = ["r", "b", "g"]
    r : int
    g : int
    b : int

이제 개체 크기가 줄어 듭니다.

>>> imp sys
>>> sys.getsizeof(Color)
1056
>>> sys.getsizeof(SlottedColor)
888

경우에 따라 __slots__인스턴스를 만들고 속성에 액세스하는 속도도 향상됩니다. 또한 슬롯은 기본 할당을 허용하지 않습니다. 그렇지 않으면 a ValueError가 발생합니다.

블로그 게시물 에서 슬롯에 대해 자세히 알아보십시오 .


요약표

+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
|       Feature        |       Keyword        |                      Example                       |           Implement in a Class          |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| Attributes           |  init                |  Color().r -> 0                                    |  __init__                               |
| Representation       |  repr                |  Color() -> Color(r=0, g=0, b=0)                   |  __repr__                               |
| Comparision*         |  eq                  |  Color() == Color(0, 0, 0) -> True                 |  __eq__                                 |
|                      |                      |                                                    |                                         |
| Order                |  order               |  sorted([Color(0, 50, 0), Color()]) -> ...         |  __lt__, __le__, __gt__, __ge__         |
| Hashable             |  unsafe_hash/frozen  |  {Color(), {Color()}} -> {Color(r=0, g=0, b=0)}    |  __hash__                               |
| Immutable            |  frozen + eq         |  Color().r = 10 -> TypeError                       |  __setattr__, __delattr__               |
|                      |                      |                                                    |                                         |
| Unpackable+          |  -                   |  r, g, b = Color()                                 |   __iter__                              |
| Optimization+        |  -                   |  sys.getsizeof(SlottedColor) -> 888                |  __slots__                              |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+

+ 이러한 메서드는 자동으로 생성되지 않으며 데이터 클래스에서 수동 구현이 필요합니다.

* __ne__ 되어 구현되지 .


추가 기능

초기화 후

@dataclasses.dataclass
class RGBA:
    r : int = 0
    g : int = 0
    b : int = 0
    a : float = 1.0

    def __post_init__(self):
        self.a : int =  int(self.a * 255)


RGBA(127, 0, 255, 0.5)
# RGBA(r=127, g=0, b=255, a=127)

계승

@dataclasses.dataclass
class RGBA(Color):
    a : int = 0

전환

재귀 적 으로 데이터 클래스를 튜플 또는 딕셔너리로 ​​변환합니다 .

>>> dataclasses.astuple(Color(128, 0, 255))
(128, 0, 255)
>>> dataclasses.asdict(Color(128, 0, 255))
{r: 128, g: 0, b: 255}

한계


참고 문헌

  • R. Hettinger의 이야기Dataclasses : 모든 코드 생성기를 종료하는 코드 생성기
  • 쉬운 수업 에 대한 T. Hunner의 강연 : 모든 문제가없는 Python 수업
  • 해싱 세부 사항에 대한 Python의 문서
  • Python 3.7의 데이터 클래스대한 궁극적 인 가이드대한 실제 Python 가이드
  • A. Python 3.7 데이터 클래스대한 간략한 둘러보기대한 Shaw의 블로그 게시물
  • E. Smith의 데이터 클래스 에 대한 github 저장소

Btw. Raymond Hettinger (Python 핵심 개발자)는 PyCon 2018에서 훌륭한 강연을했습니다.

https://www.youtube.com/watch?v=T-TwcmT6Rcw&t=1390

슬라이드는 여기에 있습니다 : https://twitter.com/raymondh/status/995693882812915712

비교


로부터 PEP 사양 :

PEP 526, "Syntax for Variable Annotations"에 정의 된대로 유형 주석이있는 변수에 대한 클래스 정의를 검사하는 클래스 데코레이터가 제공됩니다. 이 문서에서는 이러한 변수를 필드라고합니다. 데코레이터는 이러한 필드를 사용하여 생성 된 메서드 정의를 클래스에 추가하여 인스턴스 초기화, repr, 비교 메서드 및 선택적으로 사양 섹션에 설명 된 기타 메서드를 지원합니다. 이러한 클래스를 데이터 클래스라고하지만 클래스에 특별한 것은 없습니다. 데코레이터는 생성 된 메서드를 클래스에 추가하고 주어진 것과 동일한 클래스를 반환합니다.

@dataclass발전기는 달리처럼 자신을 정의하는 거라고 클래스에 메소드를 추가 __repr__, __init__, __lt__,와 __gt__.


이 간단한 수업을 고려하십시오 Foo

from dataclasses import dataclass
@dataclass
class Foo:    
    def bar():
        pass  

다음은 dir()내장 된 비교입니다. 왼쪽 Foo에는 @dataclass 데코레이터가없고 오른쪽에는 @dataclass 데코레이터가 있습니다.

여기에 이미지 설명 입력

inspect비교 를 위해 모듈을 사용한 후의 또 다른 차이점이 있습니다.

여기에 이미지 설명 입력

참고 URL : https://stackoverflow.com/questions/47955263/what-are-data-classes-and-how-are-they-different-from-common-classes

반응형