In einer weiteren Antwort fragten Sie nach der relativen Leistung dieser beiden Alternativen:
z1 = dict(x.items() + y.items())
z2 = dict(x, **y)
Zumindest auf meinem Rechner (ein ganz normaler x86_64 mit Python 2.5.2) werden alternative z2
ist nicht nur kürzer und einfacher, sondern auch wesentlich schneller. Sie können dies selbst überprüfen, indem Sie die timeit
Modul, das mit Python geliefert wird.
Beispiel 1: identische Wörterbücher, die 20 aufeinanderfolgende ganze Zahlen auf sich selbst abbilden:
% python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z1=dict(x.items() + y.items())'
100000 loops, best of 3: 5.67 usec per loop
% python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z2=dict(x, **y)'
100000 loops, best of 3: 1.53 usec per loop
z2
gewinnt mit einem Faktor von etwa 3,5. Verschiedene Wörterbücher scheinen recht unterschiedliche Ergebnisse zu liefern, aber z2
scheint immer die Nase vorn zu haben. (Wenn Sie inkonsistente Ergebnisse für die 同じ Test, versuchen Sie die Eingabe von -r
mit einer größeren Zahl als der Standardzahl 3).
Beispiel 2: Nicht überlappende Wörterbücher, die 252 kurze Zeichenketten auf ganze Zahlen abbilden und umgekehrt:
% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z1=dict(x.items() + y.items())'
1000 loops, best of 3: 260 usec per loop
% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z2=dict(x, **y)'
10000 loops, best of 3: 26.9 usec per loop
z2
gewinnt etwa um den Faktor 10. Das ist meiner Meinung nach ein ziemlich großer Gewinn!
Nachdem ich diese beiden verglichen hatte, fragte ich mich, ob z1
Das schlechte Abschneiden der beiden Listen könnte auf den Aufwand für die Erstellung der beiden Listen zurückzuführen sein, was mich wiederum zu der Frage veranlasste, ob diese Variante nicht besser funktionieren könnte:
from itertools import chain
z3 = dict(chain(x.iteritems(), y.iteritems()))
Einige schnelle Tests, z.B.
% python -m timeit -s 'from itertools import chain; from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z3=dict(chain(x.iteritems(), y.iteritems()))'
10000 loops, best of 3: 66 usec per loop
lassen mich zu dem Schluss kommen, dass z3
ist etwas schneller als z1
, aber nicht annähernd so schnell wie z2
. Es lohnt sich definitiv nicht, all die zusätzliche Tipparbeit zu leisten.
In dieser Diskussion fehlt noch etwas Wichtiges, nämlich ein Leistungsvergleich dieser Alternativen mit dem "offensichtlichen" Weg, zwei Listen zusammenzuführen: die Verwendung des update
Methode. Um zu versuchen, die Dinge gleichberechtigt mit den Ausdrücken zu halten, von denen keiner x oder y verändert, werde ich eine Kopie von x erstellen, anstatt es an Ort und Stelle zu verändern, wie folgt:
z0 = dict(x)
z0.update(y)
Ein typisches Ergebnis:
% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z0=dict(x); z0.update(y)'
10000 loops, best of 3: 26.9 usec per loop
Mit anderen Worten, z0
y z2
scheinen im Wesentlichen die gleiche Leistung zu haben. Glauben Sie, dass dies ein Zufall sein könnte? Ich weiß es nicht....
Ich würde sogar so weit gehen zu behaupten, dass es für reinen Python-Code unmöglich ist, etwas Besseres zu tun als dies. Und wenn Sie es in einem C-Erweiterungsmodul deutlich besser machen können, könnte ich mir vorstellen, dass die Python-Leute durchaus daran interessiert sein könnten, Ihren Code (oder eine Variation Ihres Ansatzes) in den Python-Kern einzubauen. Python verwendet dict
an vielen Orten; die Optimierung ihrer Abläufe ist eine große Sache.
Man könnte dies auch so schreiben
z0 = x.copy()
z0.update(y)
wie Tony, aber (nicht überraschend) hat der Unterschied in der Notation keine messbaren Auswirkungen auf die Leistung. Verwenden Sie das, was Ihnen am besten erscheint. Natürlich hat er völlig Recht, wenn er darauf hinweist, dass die Version mit zwei Sätzen viel einfacher zu verstehen ist.