Ich möchte sie kombinieren:
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
In ein einziges Wörterbuch:
{'name': 'Monty', 'age': 42, 'food': 'spam'}
Ich möchte sie kombinieren:
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
In ein einziges Wörterbuch:
{'name': 'Monty', 'age': 42, 'food': 'spam'}
Es ist erwähnenswert, dass dictionary = {zip(keys, values)}
wird nicht funktionieren. Sie müssen explizit deklarieren als dict(...)
Ich weiß nicht, warum Sie das erwarten, @FernandoWittmann. {thing}
ist ein syntaktischer Zucker zur Konstruktion einer set()
die ein Element enthalten. {*iterable}
ist ein syntaktischer Zucker zur Konstruktion einer set
die mehrere Elemente enthält. {k:v}
o {**mapping}
wird konstruieren eine dict
, aber das ist syntaktisch ganz anders.
Danke für den Kommentar, Dan. Sie haben recht. Meine Verwirrung ist entstanden, weil ich normalerweise die sintax {}
für Wörterbücher. In der Tat, wenn wir versuchen type({})
die Ausgabe ist dict
. Aber in der Tat, wenn wir versuchen type({thing})
dann lautet die Ausgabe set
.
Stellen Sie sich vor, Sie haben:
keys = ('name', 'age', 'food') values = ('Monty', 42, 'spam')
Wie lässt sich das folgende Wörterbuch am einfachsten erstellen?
dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
dict
Konstrukteur mit zip
new_dict = dict(zip(keys, values))
In Python 3 gibt zip nun einen Lazy Iterator zurück, und dies ist nun der performanteste Ansatz.
dict(zip(keys, values))
erfordert das einmalige globale Nachschlagen für jede dict
y zip
Es werden jedoch keine unnötigen Zwischendateistrukturen gebildet, und in der Funktionsanwendung müssen keine lokalen Suchvorgänge durchgeführt werden.
Der zweite Weg zur Verwendung des dict-Konstruktors ist die Verwendung der nativen Syntax eines dict-Verständnisses (nicht eines リスト Verständnis, wie es andere fälschlicherweise formuliert haben):
new_dict = {k: v for k, v in zip(keys, values)}
Wählen Sie diese Option, wenn Sie eine Zuordnung oder einen Filter auf der Grundlage von Schlüsseln oder Werten benötigen.
In Python 2, zip
eine Liste zurückgibt. Um die Erstellung einer unnötigen Liste zu vermeiden, verwenden Sie izip
stattdessen (aliased to zip kann Code-Änderungen reduzieren, wenn Sie auf Python 3 umsteigen).
from itertools import izip as zip
Das ist also immer noch (2.7):
new_dict = {k: v for k, v in zip(keys, values)}
izip
von itertools
wird zip
in Python 3. izip
ist besser als zip für Python 2 (weil es die unnötige Listenerstellung vermeidet), und ideal für 2.6 oder darunter:
from itertools import izip
new_dict = dict(izip(keys, values))
In allen Fällen:
>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}
Wenn wir uns die Hilfe auf dict
sehen wir, dass es eine Vielzahl von Argumentationsformen gibt:
>>> help(dict)
class dict(object)
| dict() -> new empty dictionary
| dict(mapping) -> new dictionary initialized from a mapping object's
| (key, value) pairs
| dict(iterable) -> new dictionary initialized as if via:
| d = {}
| for k, v in iterable:
| d[k] = v
| dict(**kwargs) -> new dictionary initialized with the name=value pairs
| in the keyword argument list. For example: dict(one=1, two=2)
Der optimale Ansatz ist die Verwendung einer Iterable, wobei die Erstellung unnötiger Datenstrukturen vermieden wird. In Python 2 erzeugt zip eine unnötige Liste:
>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
In Python 3 würde die Entsprechung lauten:
>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
und Python 3's zip
erzeugt lediglich ein iterierbares Objekt:
>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>
Da wir vermeiden wollen, unnötige Datenstrukturen zu erstellen, wollen wir in der Regel Python 2's zip
(da es eine unnötige Liste erstellt).
Dies ist ein Generator-Ausdruck, der an den dict-Konstruktor übergeben wird:
generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)
oder gleichwertig:
dict((k, v) for k, v in zip(keys, values))
Und dies ist ein Listenverständnis, das an den dict-Konstruktor übergeben wird:
dict([(k, v) for k, v in zip(keys, values)])
In den ersten beiden Fällen wird eine zusätzliche Schicht von nicht-operativen (und damit unnötigen) Berechnungen über die Zip-Iterable gelegt, und im Fall des Listenverständnisses wird unnötigerweise eine zusätzliche Liste erstellt. Ich würde erwarten, dass alle von ihnen weniger performant sind, und sicherlich nicht mehr so.
In 64 Bit Python 3.8.2 von Nix, auf Ubuntu 16.04, geordnet vom schnellsten zum langsamsten:
>>> min(timeit.repeat(lambda: dict(zip(keys, values))))
0.6695233230129816
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)}))
0.6941362579818815
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
0.8782548159942962
>>>
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)])))
1.077607496001292
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values))))
1.1840861019445583
dict(zip(keys, values))
gewinnt auch bei kleinen Mengen von Schlüsseln und Werten, aber bei größeren Mengen werden die Leistungsunterschiede größer.
Ein Kommentator sagte:
min
scheint ein schlechter Weg zu sein, um Leistung zu vergleichen. Sicherlichmean
und/odermax
wären viel nützlichere Indikatoren für die tatsächliche Nutzung.
Wir verwenden min
weil diese Algorithmen deterministisch sind. Wir wollen die Leistung der Algorithmen unter den bestmöglichen Bedingungen kennen.
Wenn sich das Betriebssystem aus irgendeinem Grund aufhängt, hat das nichts mit dem zu tun, was wir zu vergleichen versuchen, also müssen wir diese Art von Ergebnissen von unserer Analyse ausschließen.
Wenn wir die mean
Diese Art von Ereignissen würde unsere Ergebnisse stark verfälschen, und wenn wir die max
erhalten wir nur das extremste Ergebnis - dasjenige, das am ehesten von einem solchen Ereignis betroffen ist.
Ein Kommentator sagt auch:
In Python 3.6.8 ist das Diktat-Verständnis bei Verwendung von Mittelwerten tatsächlich immer noch schneller, und zwar um etwa 30 % für diese kleinen Listen. Bei größeren Listen (10k Zufallszahlen) ist das
dict
Anruf ist etwa 10 % schneller.
Ich nehme an, wir meinen dict(zip(...
mit 10k Zufallszahlen. Das klingt nach einem ziemlich ungewöhnlichen Anwendungsfall. Es macht Sinn, dass die direktesten Aufrufe in großen Datensätzen dominieren würden, und es würde mich nicht überraschen, wenn OS-Hänger dominieren, wenn man bedenkt, wie lange es dauern würde, diesen Test auszuführen, was Ihre Zahlen weiter verzerrt. Und wenn Sie Folgendes verwenden mean
ou max
Ich würde Ihre Ergebnisse als bedeutungslos betrachten.
Nehmen wir eine realistischere Größe für unsere oberen Beispiele:
import numpy
import timeit
l1 = list(numpy.random.random(100))
l2 = list(numpy.random.random(100))
Und wir sehen hier, dass dict(zip(...
ist bei größeren Datensätzen tatsächlich um etwa 20 % schneller.
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(l1, l2)}))
9.698965263989521
>>> min(timeit.repeat(lambda: dict(zip(l1, l2))))
7.9965161079890095
Ab Mitte 2019 (Python 3.7.3) finde ich unterschiedliche Zeitangaben. %%timeit liefert 1,57 \pm 0,019microsec für dict(zip(headList, textList))
& 1.95 \pm 0,030 Mikrosekunden für {k: v for k, v in zip(headList, textList)}
. Ich würde aus Gründen der Lesbarkeit und der Geschwindigkeit die erste Variante vorschlagen. Offensichtlich geht es hier um das Argument min() vs. mean() für timeit.
Es scheint, als ob Sie sagen, dass das Diktatverständnis am schnellsten ist, aber dann in der Leistungskontrolle, dict(zip(keys, values))
sieht schneller aus. Vielleicht haben Sie vergessen, etwas zu aktualisieren?
Kleine Anmerkung (weitgehend irrelevant angesichts des Auslaufens von Python 2): Sie können from future_builtins import zip
als Alternative zu from itertools import izip as zip
die den Import etwas genauer beschreibt, um die Python 3 zip
als Ersatz für reguläre zip
. Es ist genau gleichwertig, um klar zu sein ( future_builtins.zip
ist selbst nur ein Alias von itertools.izip
).
Richtig für Python2, aber in Python 3, zip
ist bereits sparsam im Speicherverbrauch. docs.python.org/3/Bibliothek/Funktionen.html#zip In der Tat können Sie sehen, dass six
用途 zip
in Python 3 zu ersetzen itertools.izip
in Python 2 pythonhosted.org/six .
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.