Was ist die bevorzugte Syntax zum Initialisieren eines Diktats: geschweifte Klammerliterale {} oder die Funktion dict ()?

212

Ich bemühe mich, Python zu lernen, und achte genau auf gängige Codierungsstandards. Dies mag wie eine sinnlose, wählerische Frage erscheinen, aber ich versuche, mich beim Lernen auf Best Practices zu konzentrieren, damit ich keine „schlechten“ Gewohnheiten verlernen muss.

Ich sehe zwei gängige Methoden zum Initialisieren eines Diktats:

a = {
    'a': 'value',
    'another': 'value',
}

b = dict( 
    a='value',
    another='value',
)

Was gilt als "pythonischer"? Welches benutzt du? Warum?

daotoad
quelle
5
Welches Tutorial verwenden Sie? Wo haben Sie Beispiele gesehen, die zu Verwirrung geführt haben?
S.Lott
2
Nun, ich habe das Python-Tutorial, Dive in Python und dann eine Vielzahl von Blogs, SO-Posts und anderen googelten Ressourcen verwendet. Die offiziellen Dokumente werden {}ziemlich einheitlich verwendet, aber ich sehe einen Großteil des expliziten dict()Ansatzes an anderer Stelle. Ich konnte den Vorteil einer expliziten Syntax erkennen, aber das Fehlen des Ansatzes in den offiziellen Dokumenten machte mich misstrauisch. Nachdem ich dies gepostet hatte, suchte ich in den Bibliotheksdokumenten nach dictder Warnung, dass Schlüssel gültige Bezeichner sein müssen, wenn ein explizites dictDiktat zum Initialisieren eines Diktats verwendet wird.
Daotoad
2
Wie ist "dict ()" expliziter als "{}"? Ich verstehe deine Verwirrung nicht. Beides scheint mir explizit. Können Sie ein Zitat oder eine Referenz angeben, mit der Sie sagen, dass "dict" "explizit" und "{}" nicht explizit ist? Woher stammt Ihrer Meinung nach diese Unterscheidung?
S.Lott
21
Die Unterscheidung ist Rechtschreibung. dict()wird geschrieben dict- es wird der Name des Typs verwendet. Die geschweiften Klammern ( {}) basieren auf Interpunktion, um den Typ zu identifizieren.
Daotoad

Antworten:

235

Geschweifte Klammern. Das Übergeben von Schlüsselwortargumenten an dict()kann eine Karte nur initialisieren, wenn die Schlüssel gültige Python-Bezeichner sind, obwohl dies in vielen Szenarien sehr gut funktioniert.

Das funktioniert:

a = {'import': 'trade', 1: 7.8}
a = dict({'import': 'trade', 1: 7.8})

Das wird nicht funktionieren:

a =                  dict(import='trade', 1=7.8)
>> SyntaxError: invalid syntax  ^
Wai Yip Tung
quelle
85

Die ersten geschweiften Klammern. Andernfalls treten Konsistenzprobleme mit Schlüsseln auf, die ungerade Zeichen enthalten, z =.

# Works fine.
a = {
    'a': 'value',
    'b=c': 'value',
}

# Eeep! Breaks if trying to be consistent.
b = dict( 
    a='value',
    b=c='value',
)
Bernstein
quelle
11
Genau aus diesem Grund könnte man die dict () -Methode für die Initialisierung bevorzugen. Sie erzwingt, dass die Wörterbuchschlüssel gültige Bezeichner sind, sodass sie beispielsweise mit ** kwargs kompatibel sind und Schlüssel gültige Attributnamen sind.
RufusVS
57

Die erste Version ist vorzuziehen:

  • Es funktioniert für alle Arten von Schlüsseln, so können Sie zum Beispiel sagen {1: 'one', 2: 'two'}. Die zweite Variante funktioniert nur für (einige) Zeichenfolgenschlüssel. Die Verwendung unterschiedlicher Syntaxarten je nach Schlüsseltyp wäre eine unnötige Inkonsistenz.
  • Es ist schneller:

    $ python -m timeit "dict(a='value', another='value')"
    1000000 loops, best of 3: 0.79 usec per loop
    $ python -m timeit "{'a': 'value','another': 'value'}"
    1000000 loops, best of 3: 0.305 usec per loop
  • Wenn die spezielle Syntax für Wörterbuchliterale nicht verwendet werden sollte, würde sie wahrscheinlich nicht existieren.
stephan
quelle
3

Ich denke, die erste Option ist besser, weil Sie auf die Werte als ['a'] oder ['other'] zugreifen werden. Die Schlüssel in Ihrem Wörterbuch sind Zeichenfolgen, und es gibt keinen Grund, so zu tun, als ob dies nicht der Fall wäre. Für mich sieht die Schlüsselwortsyntax zunächst klug aus, auf den zweiten Blick jedoch dunkel. Dies ist für mich nur dann sinnvoll, wenn Sie damit arbeiten __dict__und die Schlüsselwörter später zu Attributen werden.

geteilt durch Null
quelle
3

Zu Ihrer Information: Wenn Sie Ihrem Wörterbuch Attribute hinzufügen müssen (Dinge, die an das Wörterbuch angehängt sind, aber nicht zu den Schlüsseln gehören), benötigen Sie das zweite Formular. In diesem Fall können Sie Ihr Wörterbuch wie folgt mit Schlüsseln mit beliebigen Zeichen initialisieren:

    class mydict(dict): pass
    a = mydict()        
    a["b=c"] = 'value'
    a.test = False
Joshua Richardson
quelle
2

Manchmal dict()ist eine gute Wahl:

a=dict(zip(['Mon','Tue','Wed','Thu','Fri'], [x for x in range(1, 6)]))

mydict=dict(zip(['mon','tue','wed','thu','fri','sat','sun'],

[random.randint (0,100) für x im Bereich (0,7)]))

Deqing
quelle
2
Es gibt eine Aufzählungsfunktion, die dies besser machen könnte. Für diese Angelegenheit gibt es einen Enum-Typ, der das, was Sie hier tun, besser kann. Dies ist auch überhaupt keine Antwort auf die Frage.
Dusktreader
2

Ich benutze fast immer geschweifte Klammern; In einigen Fällen, in denen ich Tests schreibe, verwende ich jedoch das Packen / Entpacken von Schlüsselwörtern. In diesen Fällen ist dict () viel wartbarer, da ich nichts ändern muss:

a=1,
b=2,

zu:

'a': 1,
'b': 2,

Es hilft auch unter bestimmten Umständen, wenn ich denke, dass ich es zu einem späteren Zeitpunkt in ein benanntes Tupel oder eine Klasseninstanz verwandeln möchte.

In der Implementierung selbst werde ich aufgrund meiner Besessenheit von der Optimierung und wenn ich keinen besonders großen Vorteil für die Wartbarkeit sehe, immer geschweifte Klammern bevorzugen.

In Tests und bei der Implementierung würde ich nie dict () verwenden, wenn die Möglichkeit besteht, dass die Schlüssel dann oder in Zukunft hinzugefügt werden:

  • Sei nicht immer eine Saite
  • Enthält nicht nur Ziffern, ASCII-Buchstaben und Unterstriche
  • Beginnen Sie mit einer Ganzzahl ( dict(1foo=2)löst einen SyntaxError aus)
user989266
quelle