Benannte Tupel sind im Grunde einfach zu erstellende, leichtgewichtige Objekttypen. Benannte Tupelinstanzen können mithilfe der objektähnlichen Variablen-Dereferenzierung oder der Standard-Tupelsyntax referenziert werden. Sie können ähnlich wie struct
andere gängige Datensatztypen verwendet werden, außer dass sie unveränderlich sind. Sie wurden in Python 2.6 und Python 3.0 hinzugefügt, obwohl es ein Rezept für die Implementierung in Python 2.4 gibt .
Beispielsweise ist es üblich, einen Punkt als Tupel darzustellen (x, y)
. Dies führt zu Code wie dem folgenden:
pt1 = (1.0, 5.0)
pt2 = (2.5, 1.5)
from math import sqrt
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
Mit einem benannten Tupel wird es besser lesbar:
from collections import namedtuple
Point = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)
from math import sqrt
line_length = sqrt((pt1.x-pt2.x)**2 + (pt1.y-pt2.y)**2)
Benannte Tupel sind jedoch immer noch abwärtskompatibel mit normalen Tupeln, sodass Folgendes weiterhin funktioniert:
Point = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)
from math import sqrt
# use index referencing
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
# use tuple unpacking
x1, y1 = pt1
Daher sollten Sie benannte Tupel anstelle von Tupeln überall dort verwenden, wo Sie glauben, dass die Objektnotation Ihren Code pythonischer und leichter lesbar macht . Ich persönlich habe damit begonnen, sehr einfache Werttypen darzustellen, insbesondere wenn sie als Parameter an Funktionen übergeben werden. Dadurch werden die Funktionen besser lesbar, ohne den Kontext der Tupelpackung zu sehen.
Darüber hinaus können Sie auch gewöhnliche unveränderliche Klassen ersetzen , die keine Funktionen haben, sondern nur Felder. Sie können sogar Ihre benannten Tupeltypen als Basisklassen verwenden:
class Point(namedtuple('Point', 'x y')):
[...]
Wie bei Tupeln sind Attribute in benannten Tupeln jedoch unveränderlich:
>>> Point = namedtuple('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
AttributeError: can't set attribute
Wenn Sie die Werte ändern möchten, benötigen Sie einen anderen Typ. Es gibt ein praktisches Rezept für veränderbare Datensatztypen, mit dem Sie neue Werte für Attribute festlegen können.
>>> from rcdtype import *
>>> Point = recordtype('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
>>> print(pt1[0])
2.0
Mir ist jedoch keine Form einer "benannten Liste" bekannt, mit der Sie neue Felder hinzufügen können. In dieser Situation möchten Sie möglicherweise nur ein Wörterbuch verwenden. Benannte Tupel können in Wörterbücher konvertiert werden, mit pt1._asdict()
denen zurückgegeben wird, {'x': 1.0, 'y': 5.0}
und können mit allen üblichen Wörterbuchfunktionen bearbeitet werden.
Wie bereits erwähnt, sollten Sie in der Dokumentation nach weiteren Informationen suchen, aus denen diese Beispiele erstellt wurden.
__slots__
typing.NamedTuple
die Typhinweise zulassen und besonders praktisch für Unterklassen sind.namedtuple ist eine Factory-Funktion zum Erstellen einer Tupelklasse . Mit dieser Klasse können wir Tupel erstellen, die auch namentlich aufgerufen werden können.
quelle
namedtuple is a factory function for making a tuple class.
Das ist wahrscheinlich die einzig richtige Antwort hier: PEin benanntes Tupel ist ein Tupel.
Es macht alles, was ein Tupel kann.
Aber es ist mehr als nur ein Tupel.
Es ist eine bestimmte Unterklasse eines Tupels, die programmgesteuert nach Ihrer Spezifikation erstellt wird, mit benannten Feldern und einer festen Länge.
Dies erzeugt beispielsweise eine Unterklasse von Tupeln und kann nicht nur eine feste Länge haben (in diesem Fall drei), sondern überall dort verwendet werden, wo ein Tupel verwendet wird, ohne zu brechen. Dies ist als Liskov-Substituierbarkeit bekannt.
Neu in Python 3.6 können wir eine Klassendefinition verwenden
typing.NamedTuple
, um ein benanntes Tupel zu erstellen:Das Obige ist das gleiche wie das Untere, außer dass das Obige zusätzlich Typanmerkungen und eine Dokumentzeichenfolge enthält. Folgendes ist in Python 2+ verfügbar:
Dies instanziiert es:
Wir können es inspizieren und seine Attribute verwenden:
Tiefere Erklärung
Um benannte Tupel zu verstehen, müssen Sie zuerst wissen, was ein Tupel ist. Ein Tupel ist im Wesentlichen eine unveränderliche Liste (kann nicht direkt im Speicher geändert werden).
So können Sie ein normales Tupel verwenden:
Sie können ein Tupel durch iterierbares Entpacken erweitern:
Benannte Tupel sind Tupel, mit denen auf ihre Elemente nach Namen anstatt nur nach Index zugegriffen werden kann!
Sie erstellen ein benanntes Tupel wie folgt:
Sie können auch eine einzelne Zeichenfolge verwenden, deren Namen durch Leerzeichen getrennt sind. Dies ist eine etwas besser lesbare Verwendung der API:
Sie können alles tun, was Tupel können (siehe oben) sowie Folgendes tun:
Ein Kommentator fragte:
Die Typen, mit
namedtuple
denen Sie erstellen, sind im Grunde Klassen, die Sie mit einfacher Kurzform erstellen können. Behandle sie wie Klassen. Definieren Sie sie auf Modulebene, damit pickle und andere Benutzer sie finden können.Das Arbeitsbeispiel auf globaler Modulebene:
Und dies zeigt, dass die Definition nicht nachgeschlagen werden kann:
Verwenden Sie sie, wenn es Ihren Code verbessert, damit die Semantik von Tupelelementen in Ihrem Code ausgedrückt wird.
Sie können sie anstelle eines Objekts verwenden, wenn Sie andernfalls ein Objekt mit unveränderlichen Datenattributen und ohne Funktionalität verwenden würden.
Sie können sie auch in Unterklassen unterteilen, um Funktionen hinzuzufügen, z. B .:
Es wäre wahrscheinlich eine Regression, von benannten Tupeln zu Tupeln zu wechseln. Bei der Entwurfsentscheidung im Voraus geht es darum, ob die Kosten für den zusätzlichen Code die verbesserte Lesbarkeit bei Verwendung des Tupels wert sind.
Es gibt keinen zusätzlichen Speicher, der von benannten Tupeln gegenüber Tupeln verwendet wird.
Sie suchen entweder nach einem Objekt mit Schlitz, das alle Funktionen einer Liste mit statischer Größe implementiert, oder nach einer Liste mit Unterklassen, die wie ein benanntes Tupel funktioniert (und die Größe der Liste irgendwie daran hindert, ihre Größe zu ändern.)
Ein jetzt erweitertes und vielleicht sogar durch Liskov ersetzbares Beispiel des ersten:
Und um zu verwenden, einfach Unterklasse und definieren
__slots__
:quelle
Namedtuples sind eine großartige Funktion, sie sind der perfekte Container für Daten. Wenn Sie Daten "speichern" müssen, verwenden Sie Tupel oder Wörterbücher wie:
oder:
Der Wörterbuchansatz ist überwältigend, da Diktate veränderlich und langsamer als Tupel sind. Andererseits sind die Tupel unveränderlich und leicht, aber für eine große Anzahl von Einträgen in den Datenfeldern nicht lesbar.
Namedtuples sind der perfekte Kompromiss für die beiden Ansätze, die eine hervorragende Lesbarkeit, Leichtigkeit und Unveränderlichkeit aufweisen (und außerdem polymorph sind!).
quelle
ntuple.foo
vsntuple[1]
letztere viel schneller ist. Mehr dazu: stackoverflow.com/questions/2646157/…Benannte Tupel ermöglichen die Abwärtskompatibilität mit Code, der nach der folgenden Version sucht
Mit dieser Syntax kann zukünftiger Code expliziter werden
quelle
namedtuple
ist eine der einfachsten Möglichkeiten, Ihren Code zu bereinigen und lesbarer zu machen. Es dokumentiert selbst, was im Tupel passiert. Namedtuples-Instanzen sind genauso speichereffizient wie normale Tupel, da sie keine Wörterbücher pro Instanz haben, wodurch sie schneller als Wörterbücher sind.
Ohne jedes Element im Tupel zu benennen, würde es so lauten:
Es ist so viel schwieriger zu verstehen, was im ersten Beispiel vor sich geht. Bei einem Namenstupel hat jedes Feld einen Namen. Und Sie greifen eher nach Namen als nach Position oder Index zu. Stattdessen
p[1]
können wir es p.saturation nennen. Es ist leichter zu verstehen. Und es sieht sauberer aus.Das Erstellen einer Instanz des NamedTuple ist einfacher als das Erstellen eines Wörterbuchs.
Wann könnten Sie namedtuple verwenden?
p.hue
eher alsp['hue']
.Die Syntax
['x', 'y', 'z']
oder Zeichenfolge seinx y z
(ohne Kommas, nur Leerzeichen) oderx, y, z
.True
aktiviert ist , werden ungültige Feldnamen automatisch durch Positionsnamen ersetzt. Wird beispielsweise in['abc', 'def', 'ghi','abc']
konvertiert['abc', '_1', 'ghi', '_3']
, wobei das Schlüsselwort'def'
(da dies ein reserviertes Wort zum Definieren von Funktionen ist) und der doppelte Feldname entfernt werden'abc'
.True
, wird die Klassendefinition unmittelbar vor dem Erstellen gedruckt.Sie können weiterhin nach ihrer Position auf benannte Tupel zugreifen, wenn Sie dies wünschen.
p[1] == p.saturation
. Es packt immer noch wie ein normales Tupel aus.Methoden
Alle regulären Tupelmethoden werden unterstützt. Beispiel: min (), max (), len (), in, nicht in, Verkettung (+), Index, Slice usw. Und es gibt einige zusätzliche für namedtuple. Hinweis: Diese beginnen alle mit einem Unterstrich.
_replace
,_make
,_asdict
._replace
Gibt eine neue Instanz des benannten Tupels zurück, die angegebene Felder durch neue Werte ersetzt.Die Syntax
Beispiel
Hinweis : Die Feldnamen stehen nicht in Anführungszeichen. Sie sind hier Schlüsselwörter. Denken Sie daran : Tupel sind unveränderlich - auch wenn sie benannt sind und die
_replace
Methode haben. Das_replace
erzeugt einenew
Instanz; Das Original wird nicht geändert oder der alte Wert ersetzt. Sie können das neue Ergebnis natürlich in der Variablen speichern.p = p._replace(hue=169)
_make
Macht eine neue Instanz aus einer vorhandenen Sequenz oder iterierbar.
Die Syntax
Beispiel
Was ist mit dem letzten passiert? Das Element in der Klammer sollte iterierbar sein. Eine Liste oder ein Tupel in der Klammer funktioniert also, aber die Folge von Werten, ohne sie als iterable einzuschließen, gibt einen Fehler zurück.
_asdict
Gibt ein neues OrderedDict zurück, das die Feldnamen den entsprechenden Werten zuordnet .
Die Syntax
Beispiel
Referenz : https://www.reddit.com/r/Python/comments/38ee9d/intro_to_namedtuple/
Es gibt auch eine benannte Liste, die dem benannten Tupel ähnelt, aber veränderbar ist: https://pypi.python.org/pypi/namedlist
quelle
_
!Was heißt namedtuple?
Wie der Name schon sagt, ist namedtuple ein Tupel mit Namen. Im Standardtupel greifen wir über den Index auf die Elemente zu, während mit namedtuple der Benutzer den Namen für Elemente definieren kann. Dies ist sehr praktisch, insbesondere beim Verarbeiten von CSV-Dateien (Comma Separated Value) und beim Arbeiten mit komplexen und großen Datenmengen, bei denen der Code durch die Verwendung von Indizes (nicht so pythonisch) unübersichtlich wird.
Wie benutzt man sie?
lesen
Interessantes Szenario in der CSV-Verarbeitung:
quelle
In Python gibt es eine gute Verwendung von Containern, die als benanntes Tupel bezeichnet werden. Sie können zum Erstellen einer Klassendefinition verwendet werden und verfügen über alle Funktionen des ursprünglichen Tupels.
Die Verwendung des benannten Tupels wird direkt auf die Standardklassenvorlage angewendet, um eine einfache Klasse zu generieren. Diese Methode ermöglicht viel Code zur Verbesserung der Lesbarkeit und ist auch beim Definieren einer Klasse sehr praktisch.
quelle
Eine andere (neue) Möglichkeit, benanntes Tupel zu verwenden, ist die Verwendung von NamedTuple aus dem Typing-Paket: Geben Sie Hinweise in namedtuple ein
Lassen Sie uns das Beispiel der Top-Antwort in diesem Beitrag verwenden, um zu sehen, wie sie verwendet wird.
(1) Bevor Sie das benannte Tupel verwenden, lautet der Code wie folgt:
(2) Nun verwenden wir das benannte Tupel
Erben Sie die NamedTuple-Klasse und definieren Sie den Variablennamen in der neuen Klasse. Test ist der Name der Klasse.
Erstellen Sie Instanzen aus der Klasse und weisen Sie ihnen Werte zu
Verwenden Sie zur Berechnung die Variablen aus den Instanzen
quelle
Versuche dies:
Grundsätzlich
namedtuples
sind einfach zu erstellende, leichte Objekttypen. Sie verwandeln Tupel in praktische Behälter für einfache Aufgaben. Mitnamedtuples
müssen Sie keine Ganzzahlindizes verwenden, um auf Mitglieder eines Tupels zuzugreifen.Beispiele:
Code 1:
Code 2:
quelle
Alle anderen haben bereits geantwortet, aber ich denke, ich muss noch etwas hinzufügen.
Namedtuple kann intuitiv als Verknüpfung zum Definieren einer Klasse angesehen werden.
Sehen Sie sich eine umständliche und konventionelle Art an, a zu definieren
class
.Wie für
namedtuple
quelle
red_duck[0]
oderlen(red_duck)
oderfor x in red_duck: print(x)
. Außerdem sind benannte Tupel unveränderlich, sodass diese Vorgänge fehlschlagen:red_duck[0] = 2
,red_duck.foo = 'bar'
. Da sie unveränderlich sind, können benannte Tupel alsdict
Schlüssel verwendet werden.