Обзор
Вопрос решен. Однако этот ответ добавляет несколько практических примеров, чтобы помочь в базовом понимании классов данных.
Что такое классы данных 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
< / a> с более сильными тестами на равенство.
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__
также увеличивает скорость создания экземпляров и доступа к атрибутам. Кроме того, слоты не допускают назначения по умолчанию; в противном случае возникает 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 без всякой примеси em>
- документация по деталям хеширования в Python
- руководство Real Python в Полном руководстве по классам данных в Python 3.7
- в блоге на < em> Краткий обзор классов данных Python 3.7
- репозиторий github Э. Смита в классах данных
person
pylang
schedule
11.09.2018
namedtuple
s неизменяемы и не могут иметь значений по умолчанию для атрибутов, тогда как классы данных изменяемы и могут иметь их. - person jonrsharpe   schedule 23.12.2017@dataclass
не приведет к распаду сайта. - person eric   schedule 19.02.2019namedtuples
МОЖЕТ иметь значения по умолчанию. Посмотрите здесь: stackoverflow.com/questions/11351032/ - person MJB   schedule 08.08.2019