Das Hinzufügen von collections.defaultdict
in Python 2.5 reduzierte den Bedarf an dict
's setdefault
Methode erheblich . Diese Frage ist für unsere kollektive Bildung:
- Wofür ist
setdefault
heute in Python 2.6 / 2.7 noch nützlich? - Welche populären Anwendungsfälle
setdefault
wurden abgelöstcollections.defaultdict
?
python
dictionary
setdefault
Eli Bendersky
quelle
quelle
Antworten:
Man könnte sagen, es
defaultdict
ist nützlich, um Standardeinstellungen vor dem Ausfüllen des Diktats festzulegen, undsetdefault
ist nützlich, um Standardeinstellungen während oder nach dem Ausfüllen des Diktats festzulegen .Wahrscheinlich der häufigste Anwendungsfall: Gruppieren von Elementen (in unsortierten Daten, sonst Verwendung
itertools.groupby
)Manchmal möchten Sie sicherstellen, dass nach dem Erstellen eines Diktats bestimmte Schlüssel vorhanden sind.
defaultdict
funktioniert in diesem Fall nicht, da nur Schlüssel bei explizitem Zugriff erstellt werden. Denken Sie, Sie verwenden etwas HTTP-artiges mit vielen Headern - einige sind optional, aber Sie möchten Standardeinstellungen für sie:quelle
defaultdict
. Können Sie im ersten Absatz ein Beispiel geben, was Sie meinen?setdefault
. Adefaultdict
hingegen würde nicht funktionieren, wenn nicht alledefaultvalues
gleich sind (dh einige sind0
und einige sind[]
).headers = dict(optional_headers)
. Für den Fall, dass die Standardwerte nicht alle gleich sind. Das Endergebnis ist dasselbe, als ob Sie zuerst die HTTP-Header erhalten und dann die Standardeinstellungen für diejenigen festlegen, die Sie nicht erhalten haben. Und es ist durchaus brauchbar, wenn Sie bereits habenoptional_headers
. Probieren Sie meinen angegebenen 2-Schritt-Code aus und vergleichen Sie ihn mit Ihrem. Sie werden sehen, was ich meine.new.setdefault(key, []).append(value)
defaultdict
sogar noch besser ist alssetdefault
(also wo ist der Anwendungsfall jetzt?). AuchChainMap
würde besser dashttp
Beispiel IMO behandeln.Ich verwende häufig
setdefault
für Schlüsselwortargument-Dikte, wie in dieser Funktion:Es eignet sich hervorragend zum Optimieren von Argumenten in Wrappern um Funktionen, die Schlüsselwortargumente verwenden.
quelle
defaultdict
ist großartig, wenn der Standardwert statisch ist, wie eine neue Liste, aber nicht so sehr, wenn er dynamisch ist.Zum Beispiel brauche ich ein Wörterbuch, um Zeichenfolgen eindeutigen Ints zuzuordnen.
defaultdict(int)
wird immer 0 als Standardwert verwenden. Ebensodefaultdict(intGen())
ergibt immer 1.Stattdessen habe ich ein reguläres Diktat verwendet:
Beachten Sie, dass dies
dict.get(key, nextID())
nicht ausreicht, da ich später auch auf diese Werte verweisen muss.intGen
ist eine winzige Klasse, die ich baue und die ein int automatisch inkrementiert und seinen Wert zurückgibt:Wenn jemand eine Möglichkeit hat, dies zu tun,
defaultdict
würde ich es gerne sehen.quelle
intGen
mititertools.count().next
.nextID()
Der Wert von 'wird bei jedem Aufruf erhöhtmyDict.setdefault()
, auch wenn der zurückgegebene Wert nicht als a verwendet wirdstrID
. Dies scheint irgendwie verschwenderisch und veranschaulicht eines der Dinge, die ichsetdefault()
im Allgemeinen nicht mag - nämlich, dass es immer seinedefault
Argumentation bewertet , ob es tatsächlich verwendet wird oder nicht.defaultdict
:myDict = defaultdict(lambda: nextID())
. SpäterstrID = myDict[myStr]
in der Schleife.myDict = defaultdict(nextID)
?Ich verwende,
setdefault()
wenn ich einen Standardwert in einem möchteOrderedDict
. Es gibt keine Standard-Python-Sammlung, die beides kann, aber es gibt Möglichkeiten , eine solche Sammlung zu implementieren.quelle
Da die meisten Antworten Zustand
setdefault
oderdefaultdict
würden Sie einen Standardwert gesetzt , wenn ein Schlüssel nicht existiert. Ich möchte jedoch auf eine kleine Einschränkung in Bezug auf die Anwendungsfälle von hinweisensetdefault
. Wenn der Python-Interpreter ausgeführtsetdefault
wird, wertet er immer das zweite Argument für die Funktion aus, auch wenn der Schlüssel im Wörterbuch vorhanden ist. Beispielsweise:Wie Sie sehen können,
print
wurde auch ausgeführt, obwohl 2 bereits im Wörterbuch vorhanden waren. Dies ist besonders wichtig, wenn Siesetdefault
beispielsweise eine Optimierung wie zmemoization
. Wenn Sie einen rekursiven Funktionsaufruf als zweites Argument hinzufügensetdefault
, erhalten Sie keine Leistung, da Python die Funktion immer rekursiv aufruft.Da Memoization erwähnt wurde, ist die Verwendung von functools.lru_cache Decorator eine bessere Alternative, wenn Sie eine Funktion durch Memoization erweitern möchten. lru_cache behandelt die Caching-Anforderungen für eine rekursive Funktion besser.
quelle
Wie Muhammad sagte, gibt es Situationen, in denen Sie nur manchmal einen Standardwert festlegen möchten. Ein gutes Beispiel hierfür ist eine Datenstruktur, die zuerst ausgefüllt und dann abgefragt wird.
Betrachten Sie einen Versuch. Wenn beim Hinzufügen eines Wortes ein Unterknoten benötigt wird, der jedoch nicht vorhanden ist, muss er erstellt werden, um den Versuch zu erweitern. Bei der Abfrage nach dem Vorhandensein eines Wortes zeigt ein fehlender Unterknoten an, dass das Wort nicht vorhanden ist und nicht erstellt werden sollte.
Ein Standarddikt kann dies nicht tun. Stattdessen muss ein reguläres Diktat mit den Methoden get und setdefault verwendet werden.
quelle
Theoretisch
setdefault
wäre es immer noch praktisch, wenn Sie manchmal einen Standard festlegen möchten und manchmal nicht. Im wirklichen Leben bin ich auf einen solchen Anwendungsfall nicht gestoßen.Ein interessanter Anwendungsfall ergibt sich jedoch aus der Standardbibliothek (Python 2.6, _threadinglocal.py):
Ich würde sagen, dass die Verwendung
__dict__.setdefault
ein ziemlich nützlicher Fall ist.Bearbeiten : Dies ist zufällig das einzige Beispiel in der Standardbibliothek und befindet sich in einem Kommentar. Vielleicht reicht es nicht aus, die Existenz von zu rechtfertigen
setdefault
. Dennoch ist hier eine Erklärung:Objekte speichern ihre Attribute im
__dict__
Attribut. Das__dict__
Attribut ist jederzeit nach der Objekterstellung beschreibbar. Es ist auch ein Wörterbuch, keindefaultdict
. Es ist nicht sinnvoll, Objekte im allgemeinen Fall als zu haben,__dict__
da dadurchdefaultdict
jedes Objekt alle legalen Kennungen als Attribute hat. Daher kann ich keine Änderung an Python-Objekten vorhersehen__dict__.setdefault
, die entfernt werden, abgesehen davon, dass sie vollständig gelöscht werden, wenn sie als nicht nützlich erachtet wurden.quelle
__dict__
durch die Implementierung adict
, nicht adefaultdict
.setdefault
, in Python zu bleiben, aber es ist merkwürdig zu sehen, dass es jetzt fast nutzlos ist.setdefault
macht deutlich, dass Sie einem Diktat über einen Schlüssel zuweisen, der möglicherweise vorhanden ist oder nicht, und wenn er nicht vorhanden ist, möchten Sie, dass er mit einem Standardwert erstellt wird: zum Beispield.setdefault(key,[]).append(value)
. An anderer Stelle im Programm tun Sie,alist=d[k]
wo k berechnet wird, und Sie möchten eine Ausnahme auslösen, wenn k nicht in d ist (was bei einem Standarddikt möglicherweise erforderlich istassert k in d
oder sogarif not ( k in d): raise KeyError
Ein Nachteil von
defaultdict
overdict
(dict.setdefault
) ist, dass eindefaultdict
Objekt ein neues Element erstellt. JEDERZEIT wird ein nicht vorhandener Schlüssel angegeben (z . B. mit==
,print
). Auch diedefaultdict
Klasse ist im Allgemeinen viel seltener als diedict
Klasse, es ist schwieriger, sie IME zu serialisieren.PS IMO-Funktionen | Methoden, die kein Objekt mutieren sollen, sollten ein Objekt nicht mutieren.
quelle
defaultdict(lambda l=[]: l)
.Hier sind einige Beispiele für setdefault, um seine Nützlichkeit zu demonstrieren:
quelle
Ich habe die akzeptierte Antwort umgeschrieben und sie für die Neulinge erleichtert.
Zusätzlich habe ich die Methoden als Referenz kategorisiert:
quelle
Ich benutze setdefault häufig, wenn ich dies bekomme und einen Standard (!!!) in einem Wörterbuch setze. etwas häufig das os.environ Wörterbuch:
Weniger prägnant sieht das so aus:
Es ist erwähnenswert, dass Sie auch die resultierende Variable verwenden können:
Aber das ist weniger notwendig als vor dem Bestehen von Standarddiktaten.
quelle
Ein anderer Anwendungsfall, den ich nicht glaube, wurde oben erwähnt. Manchmal behalten Sie ein Cache-Diktat von Objekten anhand ihrer ID bei, wobei sich die primäre Instanz im Cache befindet, und Sie möchten den Cache festlegen, wenn dieser fehlt.
Dies ist nützlich, wenn Sie immer eine einzelne Instanz pro eindeutiger ID behalten möchten, unabhängig davon, wie Sie jedes Mal ein Objekt erhalten. Zum Beispiel, wenn Objektattribute im Speicher aktualisiert werden und das Speichern im Speicher verschoben wird.
quelle
Ein sehr wichtiger Anwendungsfall, auf den ich gerade gestoßen bin: Er
dict.setdefault()
eignet sich hervorragend für Multithread-Code, wenn Sie nur ein einziges kanonisches Objekt möchten (im Gegensatz zu mehreren Objekten, die zufällig gleich sind).Beispielsweise weist die
(Int)Flag
Aufzählung in Python 3.6.0 einen Fehler auf : Wenn mehrere Threads um ein zusammengesetztes(Int)Flag
Mitglied konkurrieren , gibt es möglicherweise mehr als einen:Die Lösung besteht darin,
setdefault()
als letzten Schritt das Speichern des berechneten zusammengesetzten Elements zu verwenden. Wenn bereits ein anderes Element gespeichert wurde, wird es anstelle des neuen Elements verwendet, wodurch eindeutige Enum-Elemente garantiert werden.quelle
[Bearbeiten] Sehr falsch! Der setdefault würde immer long_computation auslösen, wobei Python eifrig ist.
Erweiterung von Tuttles Antwort. Für mich ist der Cache-Mechanismus der beste Anwendungsfall. Anstatt:
das 3 Zeilen und 2 oder 3 Lookups verbraucht,
würde ich gerne schreiben:quelle
long_computation(x)
wird nur wenn aufgerufenx not in memo
. Während im zweitenlong_computation(x)
immer aufgerufen wird. Nur die Zuweisung ist bedingt, der entsprechende Codesetdefault
würde folgendermaßen aussehen:v = long_computation(x)
/if x not in memo:
/memo[x] = v
.Ich mag die hier gegebene Antwort:
http://stupidpythonideas.blogspot.com/2013/08/defaultdict-vs-setdefault.html
Kurz gesagt, die Entscheidung (in nicht leistungskritischen Apps) sollte auf der Grundlage getroffen werden, wie Sie die Suche nach leeren Schlüsseln nachgeschaltet behandeln möchten ( dh
KeyError
gegenüber dem Standardwert).quelle
Der andere Anwendungsfall
setdefault()
besteht darin, dass Sie den Wert eines bereits festgelegten Schlüssels nicht überschreiben möchten .defaultdict
überschreibt, währendsetdefault()
nicht. Bei verschachtelten Wörterbüchern ist es häufiger der Fall, dass Sie nur dann einen Standard festlegen möchten, wenn der Schlüssel noch nicht festgelegt ist, da Sie das aktuelle Unterwörterbuch nicht entfernen möchten. Dies ist, wenn Sie verwendensetdefault()
.Beispiel mit
defaultdict
:setdefault
überschreibt nicht:quelle