обзор
Вопрос решен. Однако этот ответ добавляет несколько практических примеров, чтобы помочь в базовом понимании классов данных.
Что такое классы данных Python и когда их лучше всего использовать?
- генераторы кода : генерировать шаблонный код; вы можете выбрать реализацию специальных методов в обычном классе или автоматическую их реализацию в классе данных.
- контейнеры данных : структуры, содержащие данные (например, кортежи и словари), часто с точками, доступ к атрибутам, например классы
namedtuple
и другие .
"изменяемые именованные кортежи по умолчанию [s]"
Вот что означает последняя фраза:
- изменяемый : по умолчанию атрибуты класса данных можно переназначить. При желании вы можете сделать их неизменяемыми (см. Примеры ниже).
- namedtuple : у вас есть доступ к атрибутам с точками, например,
namedtuple
к классу или обычному классу.
- default : атрибутам можно присвоить значения по умолчанию.
По сравнению с обычными классами вы в первую очередь экономите на вводе стандартного кода.
Характеристики
Это обзор функций класса данных (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
более строгим проверкам на равенство.
Hashable, изменяемый
@dataclasses.dataclass(unsafe_hash=True) # override base `__hash__`
class Color:
...
Хотя объект потенциально является изменяемым (возможно, нежелательным), реализован хэш.
Hashable, неизменяемый
@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
Конверсии
Преобразование DATACLASS в кортеж или Dict, рекурсивно :
>>> dataclasses.astuple(Color(128, 0, 255))
(128, 0, 255)
>>> dataclasses.asdict(Color(128, 0, 255))
{r: 128, g: 0, b: 255}
Ограничения
Ссылки
- Р. Hettinger в разговоре на Dataclasses: код генератор , чтобы закончить все генераторы коды
- Т. Ханнера разговор по проще классов: классы Python без всех хлама
- Документация Python по деталям хеширования
- Руководство Real Python по The Ultimate Guide to Data Classes in Python 3.7
- А. Шоу блоге на небольшой тур по Python классов 3.7 данных
- Репозиторий Github Э. Смита на классах данных
namedtuple
s являются неизменяемыми и не могут иметь значений по умолчанию для атрибутов, тогда как классы данных изменяемы и могут иметь их.