Python 3.7 Datenklassen
Ernesto Rico Schmidt
4. Juli 2018

Die Version 3.7 der Programmiersprache Python wurde vergangene Woche, genau nach Plan, am 27. Juni 2018 freigegeben.

Die Liste der Highlights dieser Version ist relativ lang aber ich finde eins der neuen Module besonders interessant: Datenklassen.

@dataclass

PEP 557, beschreibt die Idee und die Implementierung von Datenklassen, und fasst Funktionalität so zusammen:

A class decorator is provided which inspects a class definition for variables with type annotations as defined in PEP 526, "Syntax for Variable Annotations". In this document, such variables are called fields. Using these fields, the decorator adds generated method definitions to the class to support instance initialization, a repr, comparison methods, and optionally other methods as described in the Specification section. Such a class is called a Data Class, but there's really nothing special about the class: the decorator adds generated methods to the class and returns the same class it was given.

Es ist also ein Code-Generator, der die speziellen dunder-Methoden (für double underscore) für die Initialisierung, für die String-Repräsentation, für den Vergleich, und für die Sortierung von Objekten der Klasse, generiert. Das erspart nicht nur Arbeit beim Entwicklen, sondern vereinfacht die Wartung von diesen Methoden.

Dazu wird der Dekorator dataclass definiert, der aus einer normalen Klasse eine mit eine Reihe spezielle Methoden generiert. Die Variablen werden dabei mit ihren Datentyp gemäß dem PEP 526 annotiert.

@dataclass
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

Per Default werden die __init__-, __repr__- und die __eq__-Methode generiert.

Felder

Für den Fall, dass Felder in der Klasse enthalten sein sollen, aber bei der Initialisierung eines neuen Objekts nicht immer angegeben werden müssen, gibt es die Möglichkeit bei der Deklaration dieser Felder einen Default-Wert anzugeben:

@dataclass
class C:
    a: int      # 'a' hat kein default Wert
    b: int = 0  # 'b' hat den default Wert 0

Für den Fall, dass Felder in der Klassen enthalten sein sollen, aber in der Initialisierung eines neuen Objekt nicht angegeben werden, kann das Feld mit Hilfe der field-Funktion angepasst werden:

@dataclass
class C:
    x: int                      # __init__ enthält 'x'
    y: int = field(init=False)  # __init__ enthält nicht 'y'

Per Default wird das Feld in den generierten Methoden für die String-Repräsentation, die Initialisierung und der Vergleich berücksichtigt.

attrs

Eine bereits vorhanden Lösung für Python 2.7 bis (inklusive) 3.7 ist attrs, die zwar mehr Funktionalität anbietet als das Modul dataclasses, aber wegen der Schnelligkeit ihrer Entwicklung nicht in die Standardbibliothek von Python integriert werden kann.

attrs enthält validators, conversion, metadata und vieles mehr.