Ich habe zwei Python-Wörterbücher und möchte einen einzelnen Ausdruck schreiben, der diese beiden zusammengeführten Wörterbücher zurückgibt. Die update()
Methode wäre genau das, was ich brauche, wenn sie ihr Ergebnis zurückgibt, anstatt ein Wörterbuch direkt zu ändern.
>>> x = {'a': 1, 'b': 2}
>>> y = {'b': 10, 'c': 11}
>>> z = x.update(y)
>>> print(z)
None
>>> x
{'a': 1, 'b': 10, 'c': 11}
Wie kann ich das endgültige zusammengeführte Wörterbuch erhalten z
, nicht x
?
(Um ganz klar zu sein, dict.update()
ich suche auch nach der Konfliktbewältigung, bei der der letzte gewinnt .)
python
dictionary
merge
Carl Meyer
quelle
quelle
z = x | y
Antworten:
Für Wörterbücher
x
undy
,z
wird ein seicht aus Wörterbuch mit Werten fusioniertey
von denen ersetzenx
.In Python 3.5 oder höher:
Schreiben Sie in Python 2 (oder 3.4 oder niedriger) eine Funktion:
und nun:
In Python 3.9.0a4 oder höher (endgültiger Veröffentlichungstermin ca. Oktober 2020): PEP-584 , die hier beschrieben wurde diese weiter zu vereinfachen umgesetzt:
Erläuterung
Angenommen, Sie haben zwei Diktate und möchten diese zu einem neuen Diktat zusammenführen, ohne die ursprünglichen Diktate zu ändern:
Das gewünschte Ergebnis ist, ein neues Wörterbuch (
z
) zu erhalten, in dem die Werte zusammengeführt werden und die Werte des zweiten Dikts die Werte des ersten überschreiben.Eine neue Syntax hierfür, die in PEP 448 vorgeschlagen und ab Python 3.5 verfügbar ist, ist
Und es ist in der Tat ein einziger Ausdruck.
Beachten Sie, dass wir auch mit der wörtlichen Notation verschmelzen können:
und nun:
Es wird jetzt als im Release-Zeitplan für 3.5, PEP 478 , implementiert angezeigt und hat nun den Weg in das Dokument " Was ist neu in Python 3.5" gefunden .
Da sich jedoch viele Organisationen noch in Python 2 befinden, möchten Sie dies möglicherweise abwärtskompatibel tun. Die klassische pythonische Methode, die in Python 2 und Python 3.0-3.4 verfügbar ist, besteht darin, dies in zwei Schritten zu tun:
In beiden Ansätzen
y
wird es an zweiter Stelle stehen und seine Werte werden die Werte ersetzenx
und somit'b'
auf3
unser Endergebnis verweisen .Noch nicht in Python 3.5, möchte aber einen einzelnen Ausdruck
Wenn Sie noch nicht mit Python 3.5 arbeiten oder abwärtskompatiblen Code schreiben müssen und dies in einem einzelnen Ausdruck möchten , ist es am leistungsfähigsten, wenn Sie ihn in eine Funktion einfügen :
und dann hast du einen einzigen Ausdruck:
Sie können auch eine Funktion zum Zusammenführen einer undefinierten Anzahl von Diktaten von Null bis zu einer sehr großen Anzahl erstellen:
Diese Funktion funktioniert in Python 2 und 3 für alle Diktate. zB gegebene Diktate
a
ang
:und Schlüsselwertpaare in
g
haben Vorrang vor Diktatena
anf
und so weiter.Kritik anderer Antworten
Verwenden Sie nicht das, was Sie in der zuvor akzeptierten Antwort sehen:
In Python 2 erstellen Sie zwei Listen im Speicher für jedes Diktat, erstellen eine dritte Liste im Speicher mit einer Länge, die der Länge der ersten beiden zusammen entspricht, und verwerfen dann alle drei Listen, um das Diktat zu erstellen. In Python 3 schlägt dies fehl, da Sie zwei
dict_items
Objekte und nicht zwei Listen hinzufügen.und Sie müssten sie explizit als Listen erstellen, z
z = dict(list(x.items()) + list(y.items()))
. Dies ist eine Verschwendung von Ressourcen und Rechenleistung.In ähnlicher Weise schlägt die Vereinigung von
items()
in Python 3 (viewitems()
in Python 2.7) fehl, wenn Werte nicht zerlegbare Objekte sind (wie z. B. Listen). Selbst wenn Ihre Werte hashbar sind, ist das Verhalten in Bezug auf die Priorität undefiniert , da Mengen semantisch ungeordnet sind. Also mach das nicht:Dieses Beispiel zeigt, was passiert, wenn Werte nicht verwertbar sind:
Hier ist ein Beispiel, in dem y Vorrang haben sollte, aber stattdessen der Wert von x aufgrund der willkürlichen Reihenfolge der Mengen beibehalten wird:
Ein weiterer Hack, den Sie nicht verwenden sollten:
Dies verwendet den
dict
Konstruktor und ist sehr schnell und speichereffizient (sogar etwas mehr als unser zweistufiger Prozess), es sei denn, Sie wissen genau, was hier passiert (dh das zweite Diktat wird als Schlüsselwortargument an das Diktat übergeben Konstruktor), es ist schwer zu lesen, es ist nicht die beabsichtigte Verwendung, und so ist es nicht Pythonic.Hier ist ein Beispiel für die Verwendung in Django .
Dicts sollen Hash-Schlüssel (z. B. Frozensets oder Tupel) verwenden. Diese Methode schlägt jedoch in Python 3 fehl, wenn Schlüssel keine Zeichenfolgen sind.
Aus der Mailingliste schrieb Guido van Rossum, der Schöpfer der Sprache:
und
Es ist mein Verständnis (sowie das Verständnis des Schöpfers der Sprache ), dass die beabsichtigte Verwendung darin
dict(**y)
besteht, Diktate zu Lesbarkeitszwecken zu erstellen, z.anstatt
Antwort auf Kommentare
Auch hier funktioniert es nicht für 3, wenn Schlüssel keine Zeichenfolgen sind. Der implizite Aufrufvertrag sieht vor, dass Namespaces normale Diktate annehmen, während Benutzer nur Schlüsselwortargumente übergeben müssen, die Zeichenfolgen sind. Alle anderen Callables haben es erzwungen.
dict
hat diese Konsistenz in Python 2 gebrochen:Diese Inkonsistenz war angesichts anderer Implementierungen von Python (Pypy, Jython, IronPython) schlecht. Daher wurde es in Python 3 behoben, da diese Verwendung eine bahnbrechende Änderung sein könnte.
Ich sage Ihnen, dass es böswillige Inkompetenz ist, absichtlich Code zu schreiben, der nur in einer Version einer Sprache funktioniert oder der nur unter bestimmten willkürlichen Einschränkungen funktioniert.
Mehr Kommentare:
Meine Antwort:
merge_two_dicts(x, y)
scheint mir tatsächlich viel klarer zu sein, wenn wir uns tatsächlich Gedanken über die Lesbarkeit machen. Und es ist nicht vorwärtskompatibel, da Python 2 zunehmend veraltet ist.Ja. Ich muss Sie auf die Frage zurückführen, die eine flache Zusammenführung von zwei Wörterbüchern erfordert , wobei die Werte des ersten durch die Werte des zweiten überschrieben werden - in einem einzigen Ausdruck.
Wenn Sie zwei Wörterbücher mit Wörterbüchern annehmen, werden diese möglicherweise rekursiv in einer einzigen Funktion zusammengeführt. Sie sollten jedoch darauf achten, die Wörterbücher aus beiden Quellen nicht zu ändern. Der sicherste Weg, dies zu vermeiden, besteht darin, beim Zuweisen von Werten eine Kopie zu erstellen. Da Schlüssel hashbar sein müssen und daher normalerweise unveränderlich sind, ist es sinnlos, sie zu kopieren:
Verwendungszweck:
Eventualverbindlichkeiten für andere Werttypen zu finden, geht weit über den Rahmen dieser Frage hinaus, daher werde ich Sie auf meine Antwort auf die kanonische Frage zu einem "Zusammenführen von Wörterbüchern der Wörterbücher" hinweisen .
Weniger leistungsfähig, aber korrekte Ad-hocs
Diese Ansätze sind weniger performant, liefern jedoch ein korrektes Verhalten. Sie werden viel weniger performant als
copy
undupdate
oder das neue auspacken , weil sie durchlaufen jedes Schlüssel-Wert - Paar auf einer höheren Abstraktionsebene, aber sie tun respektieren die Rangordnung (letztere dicts haben Vorrang)Sie können die Diktate auch manuell innerhalb eines Diktatverständnisses verketten:
oder in Python 2.6 (und vielleicht schon in 2.4, als Generatorausdrücke eingeführt wurden):
itertools.chain
verkettet die Iteratoren über die Schlüssel-Wert-Paare in der richtigen Reihenfolge:Performance-Analyse
Ich werde nur die Leistungsanalyse der Verwendungen durchführen, von denen bekannt ist, dass sie sich korrekt verhalten.
Das Folgende wird unter Ubuntu 14.04 gemacht
In Python 2.7 (System Python):
In Python 3.5 (Deadsnakes PPA):
Ressourcen zu Wörterbüchern
quelle
{**{(0, 1):2}}
->{(0, 1): 2}
z = {**x, **y}
wirklich stimulieren michx | y
In Ihrem Fall können Sie Folgendes tun:
Dadurch wird, wie Sie es möchten, das endgültige Diktat
z
eingegeben und der Wert für den Schlüsselb
wird ordnungsgemäß durch deny
Wert des zweiten ( ) Diktats überschrieben :Wenn Sie Python 3 verwenden, ist es nur ein wenig komplizierter. So erstellen Sie
z
:Wenn Sie Python Version 3.9.0a4 oder höher verwenden, können Sie direkt Folgendes verwenden:
quelle
Eine Alternative:
quelle
Update
ist nicht eine der "Kern" -Funktionen, die Menschen häufig nutzen.(lambda z: z.update(y) or z)(x.copy())
Eine weitere, prägnantere Option:
Hinweis : Dies ist eine beliebte Antwort geworden. Es ist jedoch wichtig darauf hinzuweisen, dass
y
die Tatsache, dass dies überhaupt funktioniert, ein Missbrauch eines CPython-Implementierungsdetails ist und in Python 3 nicht funktioniert. oder in PyPy, IronPython oder Jython. Auch Guido ist kein Fan . Daher kann ich diese Technik nicht für vorwärtskompatiblen oder implementierungsübergreifenden tragbaren Code empfehlen, was wirklich bedeutet, dass sie vollständig vermieden werden sollte.quelle
Dies wird wahrscheinlich keine beliebte Antwort sein, aber Sie möchten dies mit ziemlicher Sicherheit nicht tun. Wenn Sie eine Kopie wünschen, die zusammengeführt werden soll, verwenden Sie copy (oder deepcopy , je nachdem, was Sie möchten) und aktualisieren Sie dann. Die beiden Codezeilen sind viel besser lesbar - pythonischer - als die Erstellung einzelner Zeilen mit .items () + .items (). Explizit ist besser als implizit.
Wenn Sie .items () (vor Python 3.0) verwenden, erstellen Sie außerdem eine neue Liste, die die Elemente aus dem Diktat enthält. Wenn Ihre Wörterbücher groß sind, ist das ziemlich viel Aufwand (zwei große Listen, die weggeworfen werden, sobald das zusammengeführte Diktat erstellt wird). update () kann effizienter arbeiten, da es das zweite Diktat Element für Element durchlaufen kann.
In Bezug auf die Zeit :
IMO lohnt sich die winzige Verlangsamung zwischen den ersten beiden für die Lesbarkeit. Darüber hinaus wurden Schlüsselwortargumente für die Wörterbucherstellung nur in Python 2.3 hinzugefügt, während copy () und update () in älteren Versionen funktionieren.
quelle
In einer nachfolgenden Antwort haben Sie nach der relativen Leistung dieser beiden Alternativen gefragt:
Zumindest auf meinem Computer (einem ziemlich normalen x86_64 mit Python 2.5.2) ist die Alternative
z2
nicht nur kürzer und einfacher, sondern auch erheblich schneller. Sie können dies selbst überprüfen, indem Sie dastimeit
mit Python gelieferte Modul verwenden.Beispiel 1: Identische Wörterbücher, die 20 aufeinanderfolgende Ganzzahlen auf sich selbst abbilden:
z2
gewinnt um den Faktor 3,5 oder so. Verschiedene Wörterbücher scheinen ganz unterschiedliche Ergebnisse zu liefern, scheinen aberz2
immer die Nase vorn zu haben. (Wenn Sie für denselben Test inkonsistente Ergebnisse erhalten , versuchen Sie,-r
eine Zahl einzugeben, die größer als die Standardzahl 3 ist.)Beispiel 2: Nicht überlappende Wörterbücher, die 252 kurze Zeichenfolgen Ganzzahlen zuordnen und umgekehrt:
z2
gewinnt um den Faktor 10. Das ist ein ziemlich großer Gewinn in meinem Buch!Nachdem ich diese beiden verglichen hatte, fragte ich mich, ob
z1
die schlechte Leistung auf den Aufwand beim Erstellen der beiden Artikellisten zurückzuführen ist, was mich wiederum zu der Frage veranlasste, ob diese Variante möglicherweise besser funktioniert:Ein paar schnelle Tests, z
Lassen Sie mich zu dem Schluss kommen, dass dies
z3
etwas schneller ist alsz1
, aber bei weitem nicht so schnell wiez2
. Auf keinen Fall die zusätzliche Eingabe wert.In dieser Diskussion fehlt noch etwas Wichtiges, nämlich ein Leistungsvergleich dieser Alternativen mit der "offensichtlichen" Art, zwei Listen zusammenzuführen: Verwenden der
update
Methode. Um zu versuchen, die Dinge mit den Ausdrücken gleichzusetzen, von denen keiner x oder y ändert, werde ich eine Kopie von x erstellen, anstatt sie an Ort und Stelle zu ändern, wie folgt:Ein typisches Ergebnis:
Mit anderen Worten,
z0
undz2
scheinen im Wesentlichen identische Leistung zu haben. Denken Sie, dass dies ein Zufall sein könnte? Ich nicht....Tatsächlich würde ich sogar behaupten, dass es für reinen Python-Code unmöglich ist, etwas Besseres zu tun. Und wenn Sie in einem C-Erweiterungsmodul deutlich besser abschneiden können, sind die Python-Leute möglicherweise daran interessiert, Ihren Code (oder eine Variation Ihres Ansatzes) in den Python-Kern zu integrieren. Python wird
dict
an vielen Orten verwendet. Die Optimierung des Betriebs ist eine große Sache.Sie können dies auch als schreiben
wie Tony, aber (nicht überraschend) hat der Unterschied in der Notation keinen messbaren Einfluss auf die Leistung. Verwenden Sie, was für Sie richtig aussieht. Natürlich hat er absolut Recht darauf hinzuweisen, dass die Version mit zwei Aussagen viel einfacher zu verstehen ist.
quelle
items()
ist nicht verkettbar unditeritems
existiert nicht.In Python 3.0 und höher können Sie verwenden,
collections.ChainMap
welche Gruppen mehrere Diktate oder andere Zuordnungen zusammenfassen, um eine einzelne, aktualisierbare Ansicht zu erstellen:Update für Python 3.5 und höher : Sie können PEP 448 Extended Dictionary Packen und Entpacken verwenden. Das geht schnell und einfach:
quelle
del
on aufrufen, löscht eine ChainMap c die erste Zuordnung dieses Schlüssels.dict
zu vermeiden, dh:dict(ChainMap({}, y, x))
Ich wollte etwas Ähnliches, aber mit der Möglichkeit anzugeben, wie die Werte auf doppelten Schlüsseln zusammengeführt wurden, habe ich dies gehackt (aber nicht intensiv getestet). Offensichtlich ist dies kein einzelner Ausdruck, sondern ein einzelner Funktionsaufruf.
quelle
Rekursiv / tief ein Diktat aktualisieren
Demonstration:
Ausgänge:
Danke rednaw für die Änderungen.
quelle
Die beste Version, die ich denken könnte, wenn ich keine Kopie verwende, wäre:
Es ist schneller als,
dict(x.items() + y.items())
aber nicht so schnell wien = copy(a); n.update(b)
, zumindest auf CPython. Diese Version funktioniert auch in Python 3 , wenn Sie änderniteritems()
zuitems()
, die durch das 2to3 - Tool automatisch erfolgt.Persönlich gefällt mir diese Version am besten, weil sie ziemlich gut beschreibt, was ich in einer einzigen funktionalen Syntax will. Das einzige kleine Problem ist, dass es nicht ganz offensichtlich ist, dass Werte von y Vorrang vor Werten von x haben, aber ich glaube nicht, dass es schwierig ist, das herauszufinden.
quelle
Python 3.5 (PEP 448) ermöglicht eine schönere Syntaxoption:
Oder auch
In Python 3.9 verwenden Sie auch | und | = mit dem folgenden Beispiel aus PEP 584
quelle
dict(x, **y)
Lösung? Wie Sie (@CarlMeyer) in der Notiz Ihrer eigenen Antwort ( stackoverflow.com/a/39858/2798610 ) erwähnt haben, hält Guido diese Lösung für illegal .dict(x, **y)
aus dem (sehr guten) Grund nicht, dass esy
nur Schlüssel enthält, die gültige Schlüsselwortargumentnamen sind (es sei denn, Sie verwenden CPython 2.7, wo der Diktatkonstruktor betrügt). Dieser Einwand / diese Einschränkung gilt nicht für PEP 448, das die**
Entpackungssyntax verallgemeinert, um Literale zu diktieren. Diese Lösung hat also die gleiche Präzision wiedict(x, **y)
ohne den Nachteil.Bei Elementen mit Schlüsseln in beiden Wörterbüchern ('b') können Sie steuern, welches in der Ausgabe landet, indem Sie das letzte setzen.
quelle
Obwohl die Frage bereits mehrmals beantwortet wurde, wurde diese einfache Lösung des Problems noch nicht aufgeführt.
Es ist so schnell wie z0 und das böse z2, aber leicht zu verstehen und zu ändern.
quelle
z4 = {}
und ändern Sie die nächste Zeile inz4 = x.copy()
- besser als nur guter Code macht keine unnötigen Dinge (was ihn noch lesbarer und wartbarer macht).Unter diesen zwielichtigen und zweifelhaften Antworten ist dieses leuchtende Beispiel der einzige gute Weg, um Diktate in Python zusammenzuführen, die vom lebenslangen Diktator Guido van Rossum selbst gebilligt wurden ! Jemand anderes schlug die Hälfte davon vor, setzte sie jedoch nicht in eine Funktion ein.
gibt:
quelle
Wenn Sie denken, Lambdas sind böse, dann lesen Sie nicht weiter. Wie gewünscht können Sie die schnelle und speichereffiziente Lösung mit einem Ausdruck schreiben:
Wie oben vorgeschlagen, ist die Verwendung von zwei Zeilen oder das Schreiben einer Funktion wahrscheinlich der bessere Weg.
quelle
Sei pythonisch. Verwenden Sie ein Verständnis :
quelle
def dictmerge(*args): return {i:d[i] for d in args for i in d}
z={k: v for d in (x, y) for k, v in d.items()}
In Python3 gibt die
items
Methode keine Liste mehr zurück , sondern eine Ansicht , die sich wie eine Menge verhält . In diesem Fall müssen Sie die festgelegte Union verwenden, da die Verkettung mit+
nicht funktioniert:Für Python3-ähnliches Verhalten in Version 2.7 sollte die
viewitems
Methode anstelle vonitems
:Ich bevorzuge diese Notation sowieso, da es natürlicher erscheint, sie als eine festgelegte Gewerkschaftsoperation zu betrachten, anstatt sie zu verketten (wie der Titel zeigt).
Bearbeiten:
Noch ein paar Punkte für Python 3. Beachten Sie zunächst, dass der
dict(x, **y)
Trick in Python 3 nur funktioniert, wenn die Schlüssely
Zeichenfolgen sind.Raymond Hettinger des Chainmap Auch Antwort ist ziemlich elegant, da es eine beliebige Anzahl von dicts als Argumente, aber aus der Dokumentation sieht es aus wie es aussieht , nacheinander durch eine Liste aller dicts für jeden Nachschlag:
Dies kann Sie verlangsamen, wenn Ihre Anwendung viele Suchvorgänge enthält:
Also um eine Größenordnung langsamer für Lookups. Ich bin ein Fan von Chainmap, sehe aber weniger praktisch aus, wenn es viele Suchvorgänge gibt.
quelle
Missbrauch führt zu einer Lösung mit einem Ausdruck für Matthews Antwort :
Sie sagten, Sie wollten einen Ausdruck, also habe ich missbraucht
lambda
, um einen Namen zu binden, und Tupel, um Lambdas Ein-Ausdruck-Limit zu überschreiben. Fühlen Sie sich frei zu erschaudern.Sie können dies natürlich auch tun, wenn Sie es nicht kopieren möchten:
quelle
Einfache Lösung mit itertools, die die Ordnung bewahrt (letztere haben Vorrang)
Und es ist Verwendung:
quelle
Zwei Wörterbücher
n Wörterbücher
sum
hat schlechte Leistung. Siehe https://mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python/quelle
Obwohl die Antworten für dieses flache Wörterbuch gut waren, führt keine der hier definierten Methoden tatsächlich eine tiefe Wörterbuchzusammenführung durch.
Beispiele folgen:
Man würde ein Ergebnis von so etwas erwarten:
Stattdessen erhalten wir Folgendes:
Der 'one'-Eintrag sollte' depth_2 'und' extra 'als Elemente in seinem Wörterbuch haben, wenn es sich wirklich um eine Zusammenführung handelt.
Die Verwendung der Kette funktioniert auch nicht:
Ergebnisse in:
Die tiefe Verschmelzung, die rcwesick gab, führt auch zum gleichen Ergebnis.
Ja, es wird funktionieren, um die Beispielwörterbücher zusammenzuführen, aber keines von ihnen ist ein generischer Mechanismus zum Zusammenführen. Ich werde dies später aktualisieren, sobald ich eine Methode schreibe, die eine echte Zusammenführung durchführt.
quelle
(Nur für Python2.7 *; es gibt einfachere Lösungen für Python3 *.)
Wenn Sie dem Importieren eines Standardbibliotheksmoduls nicht abgeneigt sind, können Sie dies tun
(Das
or a
Bit in derlambda
ist notwendig, weildict.update
immerNone
auf Erfolg zurückkehrt.)quelle
Wenn es Ihnen nichts ausmacht, zu mutieren
x
,Einfach, lesbar, performant. Sie wissen, dass
update()
immer zurückgegeben wirdNone
, was ein falscher Wert ist. Der obige Ausdruck wird alsox
nach der Aktualisierung immer ausgewertet .Mutationsmethoden in der Standardbibliothek (wie
.update()
) werden gemäßNone
Konvention zurückgegeben, sodass dieses Muster auch für diese funktioniert. Wenn Sie eine Methode verwenden, die dieser Konventionor
nicht entspricht, funktioniert sie möglicherweise nicht. Sie können jedoch stattdessen eine Tupelanzeige und einen Index verwenden, um daraus einen einzelnen Ausdruck zu machen. Dies funktioniert unabhängig davon, wie das erste Element ausgewertet wird.Wenn Sie noch keine
x
Variable haben, können Sielambda
eine lokale Variable erstellen, ohne eine Zuweisungsanweisung zu verwenden. Dies läuft darauf hinaus,lambda
als let-Ausdruck zu verwenden , was eine gängige Technik in funktionalen Sprachen ist, aber möglicherweise unpythonisch.Obwohl es sich nicht wesentlich von der folgenden Verwendung des neuen Walross-Operators unterscheidet (nur Python 3.8+):
Wenn Sie eine Kopie wünschen, ist der PEP 448-Stil am einfachsten
{**x, **y}
. Wenn dies in Ihrer (älteren) Python-Version nicht verfügbar ist , funktioniert das Let- Muster auch hier.(Das entspricht natürlich,
(z := x.copy()).update(y) or z
aber wenn Ihre Python-Version dafür neu genug ist, ist der PEP 448-Stil verfügbar.)quelle
Ich habe hier und anderswo auf Ideen zurückgegriffen und eine Funktion verstanden:
Verwendung (getestet in Python 3):
Sie könnten stattdessen ein Lambda verwenden.
quelle
Das Problem, das ich mit den bisher aufgeführten Lösungen habe, ist, dass im zusammengeführten Wörterbuch der Wert für Schlüssel "b" 10 ist, aber meiner Meinung nach sollte er 12 sein. In diesem Licht präsentiere ich Folgendes:
Ergebnisse:
quelle
cytoolz.merge_with
( toolz.readthedocs.io/en/latest/… )Es ist so dumm, dass
.update
nichts zurückgibt.Ich benutze nur eine einfache Hilfsfunktion, um das Problem zu lösen:
Beispiele:
quelle
Dies sollte Ihr Problem lösen.
quelle
Dies kann mit einem einzigen Diktatverständnis erfolgen:
Meiner Ansicht nach die beste Antwort für den Teil "Einzelausdruck", da keine zusätzlichen Funktionen benötigt werden und er kurz ist.
quelle
Dank PEP 572: Assignment Expressions wird es eine neue Option geben, wenn Python 3.8 veröffentlicht wird ( geplant für den 20. Oktober 2019 ) . Mit dem neuen Operator für Zuweisungsausdrücke können Sie das Ergebnis von zuweisen und es dennoch zum Aufrufen verwenden. Dabei bleibt der kombinierte Code ein einzelner Ausdruck anstelle von zwei Anweisungen, die sich ändern:
:=
copy
update
zu:
während sie sich in jeder Hinsicht identisch verhalten. Wenn Sie auch das Ergebnis zurückgeben müssen
dict
(Sie haben nach einem Ausdruck gefragtdict
, der das zurückgibt; das oben Gesagte erstellt und weist es zunewdict
, gibt es aber nicht zurück, sodass Sie es nicht verwenden können, um ein Argument wie es ist a la an eine Funktion zu übergebenmyfunc((newdict := dict1.copy()).update(dict2))
) , dann fügen sie einfachor newdict
bis zum Ende (daupdate
kehrtNone
, die falsy ist, wird es dann bewerten und Rückkehrnewdict
als Ergebnis des Ausdrucks):Wichtiger Vorbehalt: Im Allgemeinen würde ich diesen Ansatz zugunsten von:
Der Entpackungsansatz ist klarer (für alle, die sich mit allgemeinem Entpacken auskennen, was Sie sollten ), erfordert überhaupt keinen Namen für das Ergebnis (daher ist es viel prägnanter, wenn ein temporäres Element erstellt wird, das sofort an a übergeben wird Funktion oder in einem
list
/tuple
Literal oder ähnlichem enthalten) und ist mit ziemlicher Sicherheit auch schneller, da es (auf CPython) ungefähr gleichbedeutend ist mit:Da dies jedoch auf der C-Ebene unter Verwendung der konkreten
dict
API erfolgt, ist kein Aufwand für die Suche / Bindung dynamischer Methoden oder den Versand von Funktionsaufrufen erforderlich (wobei(newdict := dict1.copy()).update(dict2)
das Verhalten unvermeidlich identisch mit dem des ursprünglichen Zweiliners ist und die Arbeit in diskreten Schritten mit dynamischer Suche ausgeführt wird / Bindung / Aufruf von Methoden.Es ist auch erweiterbarer, da das Zusammenführen von drei
dict
Sekunden offensichtlich ist:wo die Verwendung von Zuweisungsausdrücken nicht so skaliert; Das nächste, was Sie bekommen könnten, wäre:
oder ohne das vorübergehende Tupel von
None
s, aber mit Wahrheitsprüfung jedesNone
Ergebnisses:entweder von denen offensichtlich viel häßlichere, und enthält ferner Ineffizienzen (entweder eine verschwendete temporäre
tuple
vonNone
s für komma Trennung oder sinnlos Iness Testen jedesupdate
s‘None
Rückkehr zuror
Trennung).Der einzige wirkliche Vorteil des Ansatzes für Zuweisungsausdrücke besteht darin, dass:
set
s als auchdict
s verarbeiten muss (beide unterstützencopy
undupdate
, sodass der Code ungefähr so funktioniert, wie Sie es erwarten würden).dict
selbst, und müssen den Typ und die Semantik der linken Seite beibehalten (anstatt eine Ebene zu erhaltendict
). Während diesmyspecialdict({**speciala, **specialb})
möglicherweise funktioniert, würde es eine zusätzliche temporäre Funktion beinhaltendict
, und wennmyspecialdict
Features einfachdict
nicht beibehalten werden können (z. B. reguläredict
s behalten jetzt die Reihenfolge basierend auf dem ersten Erscheinungsbild eines Schlüssels und den Wert basierend auf dem letzten Erscheinungsbild eines Schlüssels bei; Wenn die Reihenfolge basierend auf dem beibehalten wird, letztenWenn ein Schlüssel so angezeigt wird, dass ein Wert aktualisiert wird, wird er auch an das Ende verschoben. Dann wäre die Semantik falsch. Da die Version des Zuweisungsausdrucks die genannten Methoden verwendet (die vermutlich überladen sind, um sich angemessen zu verhalten), wird niemals eine erstellt Methodendict
überhaupt (esdict1
sei denn, es war bereits eindict
), wobei der ursprüngliche Typ (und die Semantik des ursprünglichen Typs) beibehalten wurden, wobei zeitliche Faktoren vermieden wurden.quelle
quelle
x
mit ihrer Kopie. Wennx
es sich um ein Funktionsargument handelt, funktioniert dies nicht (siehe Beispiel )