Огляд
Питання вирішено. Однак ця відповідь додає кілька практичних прикладів, які допомагають в базовому розумінні класів даних.
Що саме являють собою класи даних python і коли найкраще їх використовувати?
- генератори коду : генерують код котла; ви можете вибрати, щоб реалізувати спеціальні методи в звичайному класі або мати клас даних, щоб реалізувати їх автоматично.
- контейнери даних : структури, що містять дані (наприклад, кортежі та дикти), часто з пунктирним, атрибутивним доступом, наприклад класами
namedtuple
та ін .
"змінні ім'яназви з замовчуванням [s]"
Ось що означає остання фраза:
- mutable : за замовчуванням атрибути класу даних можна перепризначити. Ви можете необов'язково зробити їх непорушними (див. Приклади нижче).
- nametuple : ви вказали крапки, доступ до атрибутів, як
namedtuple
або звичайний клас.
- за замовчуванням : атрибутам можна призначити значення за замовчуванням.
Порівняно із звичайними класами, ви в першу чергу економите на введенні кодового шаблону.
Особливості
Це огляд функцій класу даних (TL; DR? Див. Зведену таблицю в наступному розділі).
Що ви отримуєте
Ось функції, які ви отримуєте за замовчуванням з класів даних.
Атрибути + Представлення + Порівняння
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__ |
| | | | |
| Unpacking+ | - | 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}
Обмеження
Список літератури
- Розмова Р. Хеттінгера про Класи даних: Генератор коду для завершення всіх генераторів коду
- Розмова Т. Ханнера про легші класи: Класи пітона без усього суворого
- Документація Python щодо деталей хешування
- Справжній посібник Python про Кінцевий посібник із класів даних у Python 3.7
- Запис у блозі А. Шоу про короткий тур по класам даних Python 3.7
- Сховище github Е. Сміта на класах даних
namedtuple
s є незмінними і не можуть мати значення за замовчуванням для атрибутів, тоді як класи даних є змінними і можуть мати їх.