2017-12-23 2 views
-1

Mit PEP 557 werden Datenklassen in die Python-Standardbibliothek eingeführt.Was sind Python-Datenklassen und wie unterscheiden sie sich von herkömmlichen Klassen?

Sie verwenden den @dataclass Decorator und sie sollen "veränderbare nameduples mit Standard" sein, aber ich bin nicht wirklich sicher, dass ich verstehe, was das eigentlich bedeutet und wie sie sich von gewöhnlichen Klassen unterscheiden.

Was genau sind Python-Datenklassen und wann ist es am besten, sie zu verwenden?

+4

Angesichts der umfangreichen Inhalte der PEP, was möchten Sie noch wissen? 'namedtuple's sind unveränderlich und können keine Standardwerte für die Attribute haben, wohingegen Datenklassen änderbar sind und diese haben können. – jonrsharpe

+1

@jonrsharpe Scheint mir vernünftig, dass es einen Stackover-Thread zum Thema geben sollte. Stackoverflow soll eine Enzyklopädie im Q & A-Format sein, nein? Die Antwort ist niemals "Schau einfach auf diese andere Website". Hier hätte es keine Downvotes geben sollen. –

Antwort

10

Datenklassen sind nur normale Klassen, die auf die Speicherung von Status ausgerichtet sind, mehr als nur eine Menge Logik enthalten. Jedes Mal, wenn Sie eine Klasse erstellen, die hauptsächlich aus Attributen besteht, haben Sie eine Datenklasse erstellt.

Was das dataclasses Modul macht, ist es leichter Datenklassen zu erstellen. Es kümmert sich um eine große Kesselplatte für Sie.

Dies ist besonders wichtig, wenn Ihre Datenklasse überprüfbar sein muss; Dies erfordert eine __hash__ Methode sowie eine __eq__ Methode. Wenn Sie eine benutzerdefinierte __repr__ Methode zur einfachen Fehlersuche hinzufügen, dass kann sehr ausführliche werden:

class InventoryItem: 
    '''Class for keeping track of an item in inventory.''' 
    name: str 
    unit_price: float 
    quantity_on_hand: int = 0 

    def __init__(
      self, 
      name: str, 
      unit_price: float, 
      quantity_on_hand: int = 0 
     ) -> None: 
     self.name = name 
     self.unit_price = unit_price 
     self.quantity_on_hand = quantity_on_hand 

    def total_cost(self) -> float: 
     return self.unit_price * self.quantity_on_hand 

    def __repr__(self) -> str: 
     return (
      'InventoryItem(' 
      f'name={self.name!r}, unit_price={self.unit_price!r}, ' 
      f'quantity_on_hand={self.quantity_on_hand!r})' 

    def __hash__(self) -> int: 
     return hash(self.name)^hash(self.unit_price)^hash(self.quantity_on_hand) 

    def __eq__(self, other) -> bool: 
     if not isinstance(other, InventoryItem): 
      return NotImplemented 
     return (
      (self.name, self.unit_price, self.quantity_on_hand) == 
      (other.name, other.unit_price, other.quantity_on_hand)) 

Mit dataclasses können Sie reduzieren sie auf:

from dataclasses import dataclass 

@dataclass(hash=True) 
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 

derselben Klasse Dekorateur auch Vergleichsmethoden erzeugen können (__lt__, __gt__, etc.) und behandeln Unveränderlichkeit.

namedtuple Klassen sind auch Datenklassen, sind aber standardmäßig unveränderlich (und sind auch Sequenzen). dataclasses sind in dieser Hinsicht viel flexibler.

Die PEP wurde von der attrs project inspiriert, die noch mehr tun kann (einschließlich Slots, Validatoren, Konverter, Metadaten usw.).

Wenn Sie einige Beispiele sehen wollen, ich day 7, day 8, day 11 und day 20 kürzlich dataclasses für einige meiner 2017 Advent of Code Lösungen verwendet werden, für die Lösungen sehen.

+0

Vielen Dank für Ihre Antwort. Es war klar, präzise und auf den Punkt. Sie haben das Konzept auf sehr einfache und verständliche Weise erklärt. – kingJulian

+0

Im ersten Beispiel verbergen Sie absichtlich Klassenmitglieder mit Instanz-Mitgliedern mit den gleichen Namen? Bitte helfen Sie, dieses Idiom zu verstehen. – VladimirLenin

+0

@VladimirLenin: Es gibt keine Klassenattribute, es gibt nur Typ Anmerkungen. Siehe [PEP 526] (https://www.python.org/dev/peps/pep-0526/), insbesondere die [* Anmerkungen zu Klassen- und Instanzvariablen *] (https://www.python.org/dev/peps/pep-0526/# Klasse-und-Instanz-Variable-Annotationen). –

1

Vom PEP specification:

Eine Klasse decorator vorgesehen ist, die für Variablen mit Typenannotationen eine Klassendefinition überprüft, wie in PEP 526 definiert ist, "Syntax für Variable Annotations". In diesem Dokument werden solche Variablen Felder genannt. Unter Verwendung dieser Felder fügt der Dekorator der Klasse generierte Methoden Definitionen hinzu, um die Instanzinitialisierung, eine Repr, Vergleichsmethoden und optional andere Methoden zu unterstützen, wie im Abschnitt Spezifikation beschrieben. Eine solche Klasse wird als Datenklasse bezeichnet, aber gibt es wirklich nichts Besonderes an der Klasse: der Dekorator fügt der Klasse generierte Methoden hinzu und gibt die gleiche Klasse zurück, die angegeben wurde.

Der @dataclass Generator fügt Methoden der Klasse, die Sie sonst selbst definieren würde wie __repr__, __init__, __lt__ und __gt__.

Verwandte Themen