typing.NamedTuple in Python

In diesem Artikel geht es um den Data Class Builder typing.NamedTuple. Es handelt sich dabei um die modernere, typisierte Variante zu collections.namedtuple, über die ihr in diesem Artikel mehr Informationen findet.

Wenn ihr collections.namedtuple kennt, dann werdet ich euch schnell mit typing.NamedTuple anfreunden. Es wird hier ebenfalls eine Klasse von tuple erzeugt. Dazu nutzt Python eine Metaklasse, die von tuple erbt. Um dies zu Demonstrieren greife ich das Beispiel aus dem Artikel zu collections.namedtuple auf und zeige die typing.NamedTuple-Version:

from typing import NamedTuple

class Hessen(NamedTuple):
    capital: str
    population: int

# Check if Hessen is a subclass of tuple
print(issubclass(Hessen, tuple))  # True

Bei typing.NamedTuple könnt ihr explizit angeben, welcher Datentyp erwartet wird. Des Weiteren kann man anhand der Ausgabe von print(issubclass(Hessen, tuple)) erkennen kann, dass es sich um eine Subklasse von tuple handelt.

Außerdem ist es möglich, den Attributen Standardwerte zuzuweisen:

from typing import NamedTuple


class Hessen(NamedTuple):
    capital: str = "Wiesbaden"
    population: int

Ein zugriff auf die Attribute erfolgt entweder über den Index oder den Namen:

from typing import NamedTuple


class Hessen(NamedTuple):
    capital: str = "Wiesbaden"
    population: int


hessen = Hessen(population=6_295_017)
# Zugriff über den Namen
print(hessen.population)  # 6295017
print(hessen.capital)  # Wiesbaden

# Zugriff über den Index
print(hessen[0])  # 6295017

# Ausgabe des NamedTuples
print(hessen)  # Hessen(population=6295017, capital='Wiesbaden')

Ein typing.NamedTuple ist unveränderlich. Nach der Erzeugung der Klasse könne die Werte nicht mehr geändert werden. Folgender Code führt zu einem AttributeError:

from typing import NamedTuple


class Hessen(NamedTuple):
    capital: str = "Wiesbaden"
    population: int

hessen = Hessen(population=7_400_000)  # -> AttributeError

Fazit

Wenn ihr möchtet, dass die Datentypen angegeben werden könne, solltet ihr typing.NamedTuple anstelle von collections.namedtuple verwenden. Beide Typen sind aber eher für kleine Datenstrukturen geeignet, bei denen sich die Werte nicht ändern sollen. Für größere Datenstrukturen bietet es sich an, eine reguläre Klasse mit dem @dataclass-Decorator zu verwenden. Bei solchen Datenklassen sind die Werte zudem veränderbar.