Warum sollte ich in Python 3.4+ Namedtuple über SimpleNamespace verwenden, wenn ich kein Diktat verwende? Sie scheinen sehr ähnlich zu sein

11

An der einen oder anderen Stelle könnten Sie auf Funktionen mit vielen Argumenten stoßen. Manchmal ist es sinnvoll, einige der Argumente zu Superargumenten zu kombinieren. Ich habe das oft mit Diktaten gemacht, aber jetzt suche ich nach besseren Möglichkeiten, es zu tun.

Ich würde gerne drehen ...

def do_something(ax, ay, az, bu, bv, c):
    # Do something

... in ...

def do_something(a, b, c):
    # Do something

... wo aund benthalten ihre Untervariationen.

Eine Möglichkeit, dies zu tun, besteht darin, Folgendes zu tun:

A = namedtuple('A', 'x, y, z')
a = A(ax, ay, az)
B = namedtuple('B', 'u, v')
b = B(bu, bv)

Dies scheint jedoch einfacher zu sein:

a = SimpleNamespace(x=ax, y=ay, z=az)
b = SimpleNamespace(u=bu, v=bv)

Was ist der Nachteil? Die Tatsache, dass aund bnicht gut getippt? Sie sind keine A- und B-Objekte?

(Übrigens, mach dir keine Sorgen um die Variablennamen. Ich verwende sie normalerweise nicht als kurze Variablennamen.)

André Christoffer Andersen
quelle
1
Es gibt an sich keine Nachteile, es sind nur verschiedene Dinge. Für den Anfang sind benannte Tupel unveränderlich, während Namespaces veränderbar sind. Ist veränderlich besser oder schlechter als unveränderlich? Es hängt davon ab, was Sie brauchen oder wollen, in vielen Fällen spielt es einfach keine Rolle. Ihre Funktion würde wahrscheinlich mit jedem Objekt mit den erforderlichen Attributen funktionieren. Wie es erstellt wird, liegt beim Aufrufer.
Hören Sie auf, Monica
@ Goyo Danke. Der "Nachteil" war eine ungeschickte Art, es zu sagen. Ich wollte nicht implizieren, dass einer von Natur aus besser ist als der andere. Ich wollte nur die Vor- und Nachteile. Danke noch einmal.
André Christoffer Andersen
1
sollte die 4. Zeile nicht wie "b = B (bu, bv)" aussehen?
Alen Siljak
@AlenSiljak Ja, das sollte es. Ich werde es jetzt reparieren.
André Christoffer Andersen

Antworten:

21

SimpleNamespaceist im Grunde nur eine schöne Fassade auf einem Wörterbuch. Sie können Eigenschaften anstelle von Indexschlüsseln verwenden. Das ist schön, da es super flexibel und einfach zu manipulieren ist.

Der Nachteil dieser Flexibilität ist, dass sie keine Struktur bietet. Es gibt nichts, was jemanden davon abhält anzurufen SimpleNamespace(x=ax, y=ay)(und del a.zirgendwann später). Wenn diese Instanz an Ihre Funktion übergeben wird, tritt die Ausnahme auf, wenn Sie versuchen, auf das Feld zuzugreifen.

Im Gegensatz dazu namedtuplekönnen Sie einen strukturierten Typ erstellen. Der Typ hat einen Namen und weiß, welche Felder er haben soll. Ohne jedes dieser Felder können Sie keine Instanz erstellen, und sie können später nicht mehr entfernt werden. Darüber hinaus ist die Instanz unveränderlich, sodass Sie wissen, dass der Wert in a.ximmer gleich ist.

Es liegt an Ihnen, zu entscheiden, ob Sie die Flexibilität benötigen, SimpleNamespacedie Ihnen geboten wird, oder ob Sie die Struktur und Garantien von bevorzugen namedtuple.

unholysampler
quelle
2

Ich mag die Antwort über strukturiert und nicht strukturiert sehr, deshalb gebe ich unten nur ein konkretes Beispiel.

SimpleNamespaceakzeptiert Schlüssel, die mit beginnen _. Wenn Sie nach einer schnellen und einfachen Möglichkeit suchen, beispielsweise JSON, das Sie nicht steuern, in Objekte mit Feldnamen umzuwandeln, ist dies sehr praktisch:

d = {"_id": 2342122, "text": "hi there!"} # Elasticsearch gives this id!
e = SimpleNamespace(**d) # works
Name = namedtuple("Name", sorted(d)) # ValueError so we can't do Name(**d)

Beachten Sie oben, dass Sie sehen können, dass namedtuplewir ein ganzes zusätzliches Objekt erhalten, das SimpleNamespaceniemals wird. Jedes SimpleNamespaceist wirklich eine "einzigartige Schneeflocke", während es namedtupleexistiert, ohne jemals mit konkreten Werten instanziiert zu werden. Wo immer Sie Abstraktionen benötigen, die sich auf konkrete Werte verallgemeinern, sollten Sie diese wahrscheinlich bevorzugen.

Alex Moore-Niemi
quelle
1

Zusammenfassung von SimpleNamespace

Es ermöglicht das Initialisieren von Attributen beim Erstellen des Objekts:

sn = SimpleNamespace(a=1, b=2)

Es bietet eine lesbare

repr(): eval(repr(sn)) == sn

Es überschreibt den Standardvergleich. Anstatt mit zu id()vergleichen, werden stattdessen Attributwerte verglichen.

Vlad Bezden
quelle