Vue d'ensemble
La question a été abordée. Cependant, cette réponse ajoute quelques exemples pratiques pour aider à la compréhension de base des classes de données.
Que sont exactement les classes de données python et quand est-il préférable de les utiliser ?
-
générateurs de codes Vous pouvez choisir d'implémenter les méthodes spéciales dans une classe ordinaire ou de les faire implémenter automatiquement par une classe de données.
-
conteneurs de données les structures qui contiennent des données (par exemple, les tuples et les dicts), souvent avec des accès en pointillés et des attributs tels que classes,
namedtuple
et autres .
"namedtuples mutables avec défaut[s]"
Voici ce que signifie cette dernière phrase :
-
mutable par défaut, les attributs des classes de données peuvent être réaffectés. Vous pouvez éventuellement les rendre immuables (voir les exemples ci-dessous).
-
namedtuple : vous avez un accès en pointillé, par attribut, comme un
namedtuple
ou une classe ordinaire.
-
par défaut : vous pouvez attribuer des valeurs par défaut aux attributs.
Par rapport aux classes communes, vous économisez surtout la saisie de code passe-partout.
Caractéristiques
Il s'agit d'un aperçu des caractéristiques des classes de données (TL;DR ? Voir le tableau récapitulatif dans la section suivante).
Ce que vous obtenez
Voici les fonctionnalités que vous obtenez par défaut des classes de données.
Attributs + Représentation + Comparaison
import dataclasses
@dataclasses.dataclass
#@dataclasses.dataclass() # alternative
class Color:
r : int = 0
g : int = 0
b : int = 0
Ces valeurs par défaut sont fournies en définissant automatiquement les mots clés suivants à True
:
@dataclasses.dataclass(init=True, repr=True, eq=True)
Ce que vous pouvez activer
Des fonctionnalités supplémentaires sont disponibles si les mots-clés appropriés sont définis comme suit True
.
Commandez
@dataclasses.dataclass(order=True)
class Color:
r : int = 0
g : int = 0
b : int = 0
Les méthodes d'ordonnancement sont maintenant implémentées (opérateurs de surcharge) : < > <= >=
), comme dans le cas de functools.total_ordering
avec des tests d'égalité plus forts.
Hachable, Mutable
@dataclasses.dataclass(unsafe_hash=True) # override base `__hash__`
class Color:
...
Bien que l'objet soit potentiellement mutable (ce qui peut être indésirable), un hachage est mis en œuvre.
Hachable, Immuable
@dataclasses.dataclass(frozen=True) # `eq=True` (default) to be immutable
class Color:
...
Un hachage est maintenant implémenté et la modification de l'objet ou l'attribution d'attributs est interdite.
Globalement, l'objet est hachable si soit unsafe_hash=True
o frozen=True
.
Voir aussi l'original table logique de hachage avec plus de détails.
Ce que vous ne comprenez pas
Pour obtenir les caractéristiques suivantes, des méthodes spéciales doivent être mises en œuvre manuellement :
Déballage
@dataclasses.dataclass
class Color:
r : int = 0
g : int = 0
b : int = 0
def __iter__(self):
yield from dataclasses.astuple(self)
Optimisation
@dataclasses.dataclass
class SlottedColor:
__slots__ = ["r", "b", "g"]
r : int
g : int
b : int
La taille de l'objet est maintenant réduite :
>>> imp sys
>>> sys.getsizeof(Color)
1056
>>> sys.getsizeof(SlottedColor)
888
Dans certaines circonstances, __slots__
améliore également la vitesse de création des instances et d'accès aux attributs. De plus, les slots n'autorisent pas les affectations par défaut ; sinon, une instance de ValueError
est soulevée.
Pour en savoir plus sur les machines à sous, voir article de blog .
Tableau récapitulatif
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| 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__ |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
<sup>+ </sup>Ces méthodes ne sont pas générées automatiquement et nécessitent une implémentation manuelle dans une classe de données.
<sup>* </sup><code>ne</code> n'est pas nécessaire et donc <a href="https://github.com/ericvsmith/dataclasses/blob/d4c87c663feb0617fd8c7e6fe0a58882c4ccd468/dataclasses.py#L882" rel="noreferrer">non appliqué </a>.
Caractéristiques supplémentaires
Post-initialisation
@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)
Héritage
@dataclasses.dataclass
class RGBA(Color):
a : int = 0
Conversions
Convertit une classe de données en un tuple ou un dict, récursivement :
>>> dataclasses.astuple(Color(128, 0, 255))
(128, 0, 255)
>>> dataclasses.asdict(Color(128, 0, 255))
{'r': 128, 'g': 0, 'b': 255}
Limites
Références
- R. Hettinger parler en Dataclasses : Le générateur de code pour mettre fin à tous les générateurs de code
- T. Hunner parler en Des cours plus faciles : Les classes Python sans tout le superflu
- Python documentation sur les détails du hachage
- Les vrais Python guide en Le guide ultime des classes de données en Python 3.7
- A. Shaw article de blog en Un bref tour d'horizon des classes de données de Python 3.7
- E. Smith Dépôt Github en classes de données
9 votes
Compte tenu de l'ampleur du contenu du PEP, que voulez-vous savoir d'autre ?
namedtuple
sont immuables et ne peuvent pas avoir de valeurs par défaut pour les attributs, alors que les classes de données sont mutables et peuvent en avoir.75 votes
@jonrsharpe Il me semble raisonnable qu'il y ait un fil de discussion stackoverflow sur le sujet. Stackoverflow est censé être une encyclopédie sous forme de questions-réponses, non ? La réponse n'est jamais "regardez simplement sur cet autre site web". Il ne devrait pas y avoir de downvotes ici.
40 votes
Il y a cinq fils de discussion sur la façon d'ajouter un élément à une liste. Une question sur
@dataclass
ne provoquera pas la désintégration du site.9 votes
@jonrsharpe
namedtuples
peuvent avoir des valeurs par défaut. Jetez un coup d'œil ici : stackoverflow.com/questions/11351032/