Was sind "benannte Tupel" in Python?

906

Beim Lesen der Änderungen in Python 3.1 fand ich etwas ... Unerwartetes:

Das Tupel sys.version_info ist jetzt ein benanntes Tupel :

Ich habe noch nie von benannten Tupeln gehört und dachte, Elemente könnten entweder durch Zahlen (wie in Tupeln und Listen) oder durch Schlüssel (wie in Diktaten) indiziert werden. Ich hätte nie gedacht, dass sie in beide Richtungen indiziert werden können.

Meine Fragen sind also:

  • Was heißen Tupel?
  • Wie benutzt man sie?
  • Warum / wann sollte ich benannte Tupel anstelle von normalen Tupeln verwenden?
  • Warum / wann sollte ich normale Tupel anstelle von benannten Tupeln verwenden?
  • Gibt es irgendeine Art von "benannter Liste" (eine veränderbare Version des benannten Tupels)?
Denilson Sá Maia
quelle

Antworten:

1196

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 structandere 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.

fmark
quelle
35
Betrachten Sie ab Python 3.7 auch Datenklassen als Alternative (Backport für 3.6 verfügbar, jedoch nicht für frühere Versionen)
innov8
3
__slots__
Wenn
Was ist der Hauptgrund für die Verwendung von rcdtype nicht Datenklassen
Voyager
Alternative zum Diktat ist das Attributwörterbuch stackoverflow.com/questions/4984647/…
mrgloom
Da dies die Antwort ist, die Sie immer finden, kann es erwähnenswert sein, dass es jetzt auch solche gibt, typing.NamedTupledie Typhinweise zulassen und besonders praktisch für Unterklassen sind.
DerWeh
101

namedtuple ist eine Factory-Funktion zum Erstellen einer Tupelklasse . Mit dieser Klasse können wir Tupel erstellen, die auch namentlich aufgerufen werden können.

import collections

#Create a namedtuple class with names "a" "b" "c"
Row = collections.namedtuple("Row", ["a", "b", "c"], verbose=False, rename=False)   

row = Row(a=1,b=2,c=3) #Make a namedtuple from the Row class we created

print row    #Prints: Row(a=1, b=2, c=3)
print row.a  #Prints: 1
print row[0] #Prints: 1

row = Row._make([2, 3, 4]) #Make a namedtuple from a list of values

print row   #Prints: Row(a=2, b=3, c=4)
Der Demz
quelle
5
Ausführliche und Umbenennungsparameter sind standardmäßig auf False gesetzt, sodass sie nicht explizit auf diesen Wert gesetzt werden müssen.
Trismegistos
namedtuple is a factory function for making a tuple class.Das ist wahrscheinlich die einzig richtige Antwort hier: P
Mr_and_Mrs_D
90

Was heißen Tupel?

Ein 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 verwendentyping.NamedTuple, um ein benanntes Tupel zu erstellen:

from typing import NamedTuple

class ANamedTuple(NamedTuple):
    """a docstring"""
    foo: int
    bar: str
    baz: list

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:

>>> from collections import namedtuple
>>> class_name = 'ANamedTuple'
>>> fields = 'foo bar baz'
>>> ANamedTuple = namedtuple(class_name, fields)

Dies instanziiert es:

>>> ant = ANamedTuple(1, 'bar', [])

Wir können es inspizieren und seine Attribute verwenden:

>>> ant
ANamedTuple(foo=1, bar='bar', baz=[])
>>> ant.foo
1
>>> ant.bar
'bar'
>>> ant.baz.append('anything')
>>> ant.baz
['anything']

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:

>>> student_tuple = 'Lisa', 'Simpson', 'A'
>>> student_tuple
('Lisa', 'Simpson', 'A')
>>> student_tuple[0]
'Lisa'
>>> student_tuple[1]
'Simpson'
>>> student_tuple[2]
'A'

Sie können ein Tupel durch iterierbares Entpacken erweitern:

>>> first, last, grade = student_tuple
>>> first
'Lisa'
>>> last
'Simpson'
>>> grade
'A'

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:

>>> from collections import namedtuple
>>> Student = namedtuple('Student', ['first', 'last', 'grade'])

Sie können auch eine einzelne Zeichenfolge verwenden, deren Namen durch Leerzeichen getrennt sind. Dies ist eine etwas besser lesbare Verwendung der API:

>>> Student = namedtuple('Student', 'first last grade')

Wie benutzt man sie?

Sie können alles tun, was Tupel können (siehe oben) sowie Folgendes tun:

>>> named_student_tuple = Student('Lisa', 'Simpson', 'A')
>>> named_student_tuple.first
'Lisa'
>>> named_student_tuple.last
'Simpson'
>>> named_student_tuple.grade
'A'
>>> named_student_tuple._asdict()
OrderedDict([('first', 'Lisa'), ('last', 'Simpson'), ('grade', 'A')])
>>> vars(named_student_tuple)
OrderedDict([('first', 'Lisa'), ('last', 'Simpson'), ('grade', 'A')])
>>> new_named_student_tuple = named_student_tuple._replace(first='Bart', grade='C')
>>> new_named_student_tuple
Student(first='Bart', last='Simpson', grade='C')

Ein Kommentator fragte:

Wo definiert man in einem großen Skript oder Programm normalerweise ein benanntes Tupel?

Die Typen, mit namedtupledenen 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:

>>> from collections import namedtuple
>>> NT = namedtuple('NT', 'foo bar')
>>> nt = NT('foo', 'bar')
>>> import pickle
>>> pickle.loads(pickle.dumps(nt))
NT(foo='foo', bar='bar')

Und dies zeigt, dass die Definition nicht nachgeschlagen werden kann:

>>> def foo():
...     LocalNT = namedtuple('LocalNT', 'foo bar')
...     return LocalNT('foo', 'bar')
... 
>>> pickle.loads(pickle.dumps(foo()))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <class '__main__.LocalNT'>: attribute lookup LocalNT on __main__ failed

Warum / wann sollte ich benannte Tupel anstelle von normalen Tupeln verwenden?

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 .:

class Point(namedtuple('Point', 'x y')):
    """adding functionality to a named tuple"""
        __slots__ = ()
        @property
        def hypot(self):
            return (self.x ** 2 + self.y ** 2) ** 0.5
        def __str__(self):
            return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)

Warum / wann sollte ich normale Tupel anstelle von benannten Tupeln verwenden?

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.

Gibt es irgendeine Art von "benannter Liste" (eine veränderbare Version des benannten Tupels)?

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:

from collections import Sequence

class MutableTuple(Sequence): 
    """Abstract Base Class for objects that work like mutable
    namedtuples. Subclass and define your named fields with 
    __slots__ and away you go.
    """
    __slots__ = ()
    def __init__(self, *args):
        for slot, arg in zip(self.__slots__, args):
            setattr(self, slot, arg)
    def __repr__(self):
        return type(self).__name__ + repr(tuple(self))
    # more direct __iter__ than Sequence's
    def __iter__(self): 
        for name in self.__slots__:
            yield getattr(self, name)
    # Sequence requires __getitem__ & __len__:
    def __getitem__(self, index):
        return getattr(self, self.__slots__[index])
    def __len__(self):
        return len(self.__slots__)

Und um zu verwenden, einfach Unterklasse und definieren __slots__:

class Student(MutableTuple):
    __slots__ = 'first', 'last', 'grade' # customize 


>>> student = Student('Lisa', 'Simpson', 'A')
>>> student
Student('Lisa', 'Simpson', 'A')
>>> first, last, grade = student
>>> first
'Lisa'
>>> last
'Simpson'
>>> grade
'A'
>>> student[0]
'Lisa'
>>> student[2]
'A'
>>> len(student)
3
>>> 'Lisa' in student
True
>>> 'Bart' in student
False
>>> student.first = 'Bart'
>>> for i in student: print(i)
... 
Bart
Simpson
A
Aaron Hall
quelle
44

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:

user = dict(name="John", age=20)

oder:

user = ("John", 20)

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!).

Pygabriel
quelle
9
Beachten Sie, dass namedtuples sind viel langsamer als dicts , wenn Sie ihre Attribute zugreifen , indem Sie Name: ntuple.foovs ntuple[1]letztere viel schneller ist. Mehr dazu: stackoverflow.com/questions/2646157/…
Rotareti
28

Benannte Tupel ermöglichen die Abwärtskompatibilität mit Code, der nach der folgenden Version sucht

>>> sys.version_info[0:2]
(3, 1)

Mit dieser Syntax kann zukünftiger Code expliziter werden

>>> sys.version_info.major
3
>>> sys.version_info.minor
1
John La Rooy
quelle
12

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.

from collections import namedtuple

Color = namedtuple('Color', ['hue', 'saturation', 'luminosity'])

 p = Color(170, 0.1, 0.6)
 if p.saturation >= 0.5:
     print "Whew, that is bright!"
 if p.luminosity >= 0.5:
     print "Wow, that is light"

Ohne jedes Element im Tupel zu benennen, würde es so lauten:

p = (170, 0.1, 0.6)
if p[1] >= 0.5:
    print "Whew, that is bright!"
if p[2]>= 0.5:
   print "Wow, that is light"

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.

# dictionary
>>>p = dict(hue = 170, saturation = 0.1, luminosity = 0.6)
>>>p['hue']
170

#nametuple
>>>from collections import namedtuple
>>>Color = namedtuple('Color', ['hue', 'saturation', 'luminosity'])
>>>p = Color(170, 0.1, 0.6)
>>>p.hue
170

Wann könnten Sie namedtuple verwenden?

  1. Wie bereits erwähnt, erleichtert das Namedtuple das Verständnis von Tupeln erheblich. Wenn Sie also auf die Elemente im Tupel verweisen müssen, ist es nur sinnvoll, sie als benannte Tupel zu erstellen.
  2. Namedtuple ist nicht nur leichter als ein Wörterbuch, sondern behält auch die Reihenfolge im Gegensatz zum Wörterbuch bei.
  3. Wie im obigen Beispiel ist es einfacher, eine Instanz von namedtuple als ein Wörterbuch zu erstellen. Die Referenzierung des Elements im genannten Tupel sieht sauberer aus als ein Wörterbuch. p.hueeher als p['hue'].

Die Syntax

collections.namedtuple(typename, field_names[, verbose=False][, rename=False])
  • namedtuple befindet sich in der Sammlungsbibliothek.
  • Typname: Dies ist der Name der neuen Tupel-Unterklasse.
  • Feldnamen: Eine Folge von Namen für jedes Feld. Es kann eine Sequenz wie in einer Liste ['x', 'y', 'z']oder Zeichenfolge sein x y z(ohne Kommas, nur Leerzeichen) oder x, y, z.
  • Umbenennen: Wenn Umbenennen Trueaktiviert 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'.
  • verbose: Wenn verbose ist 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

somenamedtuple._replace(kwargs)

Beispiel

>>>from collections import namedtuple

>>>Color = namedtuple('Color', ['hue', 'saturation', 'luminosity'])
>>>p = Color(170, 0.1, 0.6)

>>>p._replace(hue=87)
Color(87, 0.1, 0.6)

>>>p._replace(hue=87, saturation=0.2)
Color(87, 0.2, 0.6)

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 _replaceMethode haben. Das _replaceerzeugt eine newInstanz; 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

somenamedtuple._make(iterable)

Beispiel

 >>>data = (170, 0.1, 0.6)
 >>>Color._make(data)
Color(hue=170, saturation=0.1, luminosity=0.6)

>>>Color._make([170, 0.1, 0.6])  #the list is an iterable
Color(hue=170, saturation=0.1, luminosity=0.6)

>>>Color._make((170, 0.1, 0.6))  #the tuple is an iterable
Color(hue=170, saturation=0.1, luminosity=0.6)

>>>Color._make(170, 0.1, 0.6) 
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<string>", line 15, in _make
TypeError: 'float' object is not callable

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

somenamedtuple._asdict()

Beispiel

 >>>p._asdict()
OrderedDict([('hue', 169), ('saturation', 0.1), ('luminosity', 0.6)])

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

Kevin Zhu
quelle
Beachten Sie jedoch, dass gemäß PEP8 ein einzelner Unterstrich als „schwacher Indikator für den internen Gebrauch“ mit eigenem Verhalten betrachtet wird. Vorsicht bei der Verwendung von Funktionen, die mit beginnen _!
Jens
8

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?

>>>from collections import namedtuple
>>>saleRecord = namedtuple('saleRecord','shopId saleDate salesAmout totalCustomers')
>>>
>>>
>>>#Assign values to a named tuple 
>>>shop11=saleRecord(11,'2015-01-01',2300,150) 
>>>shop12=saleRecord(shopId=22,saleDate="2015-01-01",saleAmout=1512,totalCustomers=125)

lesen

>>>#Reading as a namedtuple
>>>print("Shop Id =",shop12.shopId)
12
>>>print("Sale Date=",shop12.saleDate)
2015-01-01
>>>print("Sales Amount =",shop12.salesAmount)
1512
>>>print("Total Customers =",shop12.totalCustomers)
125

Interessantes Szenario in der CSV-Verarbeitung:

from csv import reader
from collections import namedtuple

saleRecord = namedtuple('saleRecord','shopId saleDate totalSales totalCustomers')
fileHandle = open("salesRecord.csv","r")
csvFieldsList=csv.reader(fileHandle)
for fieldsList in csvFieldsList:
    shopRec = saleRecord._make(fieldsList)
    overAllSales += shopRec.totalSales;

print("Total Sales of The Retail Chain =",overAllSales)
Saravanan Subramanian
quelle
5

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.

Marcus Thornton
quelle
2

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:

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)
print(line_length)

(2) Nun verwenden wir das benannte Tupel

from typing import NamedTuple, Number

Erben Sie die NamedTuple-Klasse und definieren Sie den Variablennamen in der neuen Klasse. Test ist der Name der Klasse.

class test(NamedTuple):
x: Number
y: Number

Erstellen Sie Instanzen aus der Klasse und weisen Sie ihnen Werte zu

pt1 = test(1.0, 5.0)   # x is 1.0, and y is 5.0. The order matters
pt2 = test(2.5, 1.5)

Verwenden Sie zur Berechnung die Variablen aus den Instanzen

line_length = sqrt((pt1.x-pt2.x)**2 + (pt1.y-pt2.y)**2)
print(line_length)
Richard Liang
quelle
1

Versuche dies:

collections.namedtuple()

Grundsätzlich namedtuplessind einfach zu erstellende, leichte Objekttypen. Sie verwandeln Tupel in praktische Behälter für einfache Aufgaben. Mit namedtuplesmüssen Sie keine Ganzzahlindizes verwenden, um auf Mitglieder eines Tupels zuzugreifen.

Beispiele:

Code 1:

>>> from collections import namedtuple

>>> Point = namedtuple('Point','x,y')

>>> pt1 = Point(1,2)

>>> pt2 = Point(3,4)

>>> dot_product = ( pt1.x * pt2.x ) +( pt1.y * pt2.y )

>>> print dot_product
11

Code 2:

>>> from collections import namedtuple

>>> Car = namedtuple('Car','Price Mileage Colour Class')

>>> xyz = Car(Price = 100000, Mileage = 30, Colour = 'Cyan', Class = 'Y')

>>> print xyz

Car(Price=100000, Mileage=30, Colour='Cyan', Class='Y')
>>> print xyz.Class
Y
Saarthak Johari
quelle
-1

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.

class Duck:
    def __init__(self, color, weight):
        self.color = color
        self.weight = weight
red_duck = Duck('red', '10')

    In [50]: red_duck
    Out[50]: <__main__.Duck at 0x1068e4e10>
    In [51]: red_duck.color
    Out[51]: 'red'

Wie für namedtuple

from collections import namedtuple
Duck = namedtuple('Duck', ['color', 'weight'])
red_duck = Duck('red', '10')

In [54]: red_duck
Out[54]: Duck(color='red', weight='10')
In [55]: red_duck.color
Out[55]: 'red'
Infinitesimalrechnung
quelle
2
Entschuldigung, aber das ist falsch. Das benannte Tupel unterstützt auch diese: red_duck[0]oder len(red_duck)oder for 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 als dictSchlüssel verwendet werden.
Denilson Sá Maia
Ja, das sind die Grundlagen.
Kalkül
1
@JawSaw Nein, es sind nicht die "Grundlagen". Benannte Tupel unterstützen einen völlig anderen Funktionsumfang als reguläre Klassen. Während benannte Tupel im Wesentlichen eine Klasse sind, bedeutet dies nicht, dass Klassen Tupel genannt werden.
Verbinden Sie Ihr Ladegerät