Geben Sie Hinweise in namedtuple ein

Lesezeit: 4 Minuten

Benutzeravatar von Pavel Hanpari
Paul Hanpari

Betrachten Sie den folgenden Codeabschnitt:

from collections import namedtuple
point = namedtuple("Point", ("x:int", "y:int"))

Der obige Kodex ist nur eine Möglichkeit zu demonstrieren, was ich zu erreichen versuche. Ich würde gerne machen namedtuple mit Typhinweisen.

Kennen Sie einen eleganten Weg, um das gewünschte Ergebnis zu erzielen?

Benutzeravatar von Wolfgang Kühn
Wolfgang Kühn

Die bevorzugte Syntax für ein typisiertes benanntes Tupel seit 3.6 ist

from typing import NamedTuple

class Point(NamedTuple):
    x: int
    y: int = 1  # Set default value

Point(3)  # -> Point(x=3, y=1)

Bearbeiten
Erwägen Sie ab Python 3.7 die Verwendung von dataclasses (Ihre IDE unterstützt sie möglicherweise noch nicht für die statische Typprüfung):

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int = 1  # Set default value

Point(3)  # -> Point(x=3, y=1)

  • @JohnE; Das OP hat ausdrücklich nach benannten Tupeln gefragt. Ja, viele Anwendungsfälle von benannten Tupeln werden besser von Datenklassen bedient. Aber um das Hervorragende zu zitieren Warum nicht benannte Tupel: Wenn Sie ein Tupel mit Namen wollen, wählen Sie auf jeden Fall ein benanntes Tupel

    – Wolfgang Kühn

    30. Juli 2018 um 14:14 Uhr

  • Mit Datenklassen ist es nicht möglich, das resultierende Objekt wie ein Tupel zu dekonstruieren

    – VARAK

    24. Oktober 2019 um 12:33 Uhr

  • Ein Tupel ist unveränderlich. Eine Datenklasse ist nicht (standardmäßig) Sie hat das eingefrorene Flag, das dem Verhalten von Tuple nahe kommt. Nur etwas, dessen man sich bewusst sein sollte.

    – shao.lo

    2. Dezember 2019 um 22:22 Uhr

  • Wenn Dataclass für Sie funktioniert, können Sie weiter gehen und verwenden pydantisch Paket, um die Typüberprüfung zur Laufzeit auf elegante Weise zu erzwingen.

    – izkeros

    18. Februar 2021 um 7:42 Uhr

  • Datenklassen sind nicht abonnierbar, und sie sind auch nicht entpackbar, während sie wie benannte Tupel iterieren, daher denke ich, dass sie weit davon entfernt sind, eine perfekte Alternative zu sein.

    – Vichoko

    18. Oktober 2021 um 21:56 Uhr

Benutzeravatar von Bhargav Rao
Bhargav Rao

Sie können verwenden typing.NamedTuple

Aus den Dokumenten

Typisierte Version von namedtuple.

>>> import typing
>>> Point = typing.NamedTuple("Point", [('x', int), ('y', int)])

Dies ist nur in Python 3.5 und höher vorhanden

  • Ich habe es so deklariert: GeoPoint = NamedTuple('GeoPoint', [('longitude', float), ('latitude', float)]) dann versuche ich geo = GeoPoint(**data) wobei Daten Diktat sind, die benötigte Schlüssel und Werte enthalten decimal.Decimalund es passiert keine Umwandlung in Float ;( auch kein Typfehler 🙁 🙁 also wie das typing.NamedTuple funktioniert? sehen gist.github.com/andilabs/15002176b2bda786b9037077fa06cc71

    – Andilabs

    21. Mai 2017 um 23:46 Uhr


  • Die @andi-Eingabe erzwingt oder wandelt keine Variablen, afaik.

    – Bhargav Rao

    22. Mai 2017 um 9:10 Uhr

  • In neueren Versionen können Sie NamedTuples als deklarieren Point = typing.NamedTuple("Point", x=int, y=int)die viel sauberer und kürzer ist.

    – Als Duplikat markiert

    11. Oktober 2021 um 20:56 Uhr

  • ^ Dokumentation, Diskussion und Beispiele, die für diese Syntax herumschwirren, sind fast nicht vorhanden. Ich habe es nur in gefunden die Datei cpython typing.py. Es besagt, dass die Syntax ab 3.6+ verfügbar ist und mindestens im Code von 3.7+ enthalten ist. Es scheint jedoch keine sauberere Version davon zu geben, um Standardwerte neben der Member-/Typdeklaration festzulegen.

    – JWCS

    10. Februar um 19:46 Uhr


  • @JWCS in der Tat. Was eigentlich schade ist. Die Klassensyntax ist manchmal übertrieben.

    – Kleinbuchstaben00

    22. Juli um 19:09 Uhr

Benutzeravatar von mrvol
Mrvol

Nur um fair zu sein, NamedTuple aus typing:

>>> from typing import NamedTuple
>>> class Point(NamedTuple):
...     x: int
...     y: int = 1  # Set default value
...
>>> Point(3)
Point(x=3, y=1)

gleich klassisch namedtuple:

>>> from collections import namedtuple
>>> p = namedtuple('Point', 'x,y', defaults=(1, ))
>>> p.__annotations__ = {'x': int, 'y': int}
>>> p(3)
Point(x=3, y=1)

So, NamedTuple ist nur Syntaxzucker für namedtuple

Unten finden Sie eine Erstellung NamedTuple Funktion aus dem Quellcode von python 3.10. Wie wir sehen können, verwendet es collections.namedtuple Konstruktor und fügt hinzu __annotations__ aus extrahierten Typen:

def _make_nmtuple(name, types, module, defaults = ()):
    fields = [n for n, t in types]
    types = {n: _type_check(t, f"field {n} annotation must be a type")
             for n, t in types}
    nm_tpl = collections.namedtuple(name, fields,
                                    defaults=defaults, module=module)
    nm_tpl.__annotations__ = nm_tpl.__new__.__annotations__ = types
    return nm_tpl

  • Syntaktischer Zucker ist etwas das Parser kann durch eine grundlegendere Syntax ersetzt werden. NamedTuple ist etwas komplizierter, da es sich um eine Funktion handelt, die zur Laufzeit tatsächlich etwas tut.

    – chepner

    17. November 2021 um 18:05 Uhr

  • Ja, ich weiß, was es während der Laufzeit tut. Es extrahiert Typen und fügt sie hinzu __annotations__ attr von gerade erstellt namedtuple Konstruktor verwenden collections.namedtuple. Ich habe diesen Code zum besseren Verständnis zur Antwort hinzugefügt.

    – Mrvol

    17. November 2021 um 20:47 Uhr

1436060cookie-checkGeben Sie Hinweise in namedtuple ein

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy