[PYTHON] Erstellen Sie ein Standarddikt, das ein Standarddikt zurückgibt, um eine Welt zu erstellen, in der KeyErrror nicht auftritt (+ JSON-Parsing-Beispiel).

Die meisten Dinge, die jeder liebt, sind vorbereitet und interessant.

Erstellen Sie ein Standarddiktat, das ein Standarddiktat zurückgibt, um eine Welt zu erstellen, in der kein Schlüsselfehler auftritt

defaultdict ist eine Erweiterungsklasse von dict, die das Verhalten festlegen kann, wenn der Schlüssel nicht gefunden wird.

8.3. Sammlungen - Hochleistungscontainer-Datentypen - Python 2.7ja1-Dokumentation

Es ist sehr praktisch, es für die Aggregationsverarbeitung usw. zu verwenden, da es nicht erforderlich ist, das Verhalten in Abhängigkeit vom Vorhandensein oder Fehlen des Schlüssels zu klassifizieren. Dies ist ein Nachdruck des Verwendungsbeispiels, aber wahrscheinlich am einfachsten zu verstehen.

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
...     d[k].append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

Es gibt ein Beispiel für die Verwendung als Zähler. Wenn Sie es jedoch als einfachen Zähler verwenden möchten, wird empfohlen, collection.Counter [^ counter] zu berücksichtigen.

[^ counter]: 8.3. Sammlungen - Hochleistungscontainer-Datentyp - Python 2.7ja1-Dokumentation

Wird in verschachtelten Wörterbüchern verwendet

Wenn Sie beispielsweise in einem verschachtelten Wörterbuch "d ['a'] ['b'] ['c']" aufrufen, auch wenn "d" "defaultdict" ist, wird "d ['a'] Wenn der Wert von "das normale" Diktat ist, kann "Schlüsselfehler" auftreten. Versuchen Sie daher Folgendes für die "default_factory", die an das "defaultdict" übergeben wird.

def _factory():
    return collections.defaultdict(_factory)

Damit haben wir eine Welt, in der "KeyErrror" nicht auftritt: accept :.

>>> import collections
>>> def _factory():
...     return collections.defaultdict(_factory)
... 
>>> d = collections.defaultdict(_factory)
>>> d['a']
defaultdict(<function _factory at 0x105e93aa0>, {})
>>> d['a']['b']
defaultdict(<function _factory at 0x105e93aa0>, {})
>>> d['a']['b'][1]
defaultdict(<function _factory at 0x105e93aa0>, {})
>>> d[1][1][0][1][1][1][1][1]
defaultdict(<function _factory at 0x105e93aa0>, {})

Beispiel für die Verwendung von JSON beim Parsen

Wenden wir das obige Beispiel auf ein reales Verwendungsbeispiel an. Das Folgende ist nur ein Gedanke allein, daher gibt es möglicherweise einen saubereren Weg, um es einfacher zu machen. Bitte sag es mir, wenn du es weißt.

Angenommen, Sie haben die folgenden JSON-Kursinformationen für Online-Kurse. Ich mag die "Adresse" nicht. Es kann einen Schlüssel geben oder nicht.

{  
  "class":{  
    "id":1,
    "subject":"Math",
    "students":[  
      {  
        "name":"Alice",
        "age":30
      },
      {  
        "name":"Bob",
        "age":40,
        "address":{  
          "country":"JP"
        }
      },
      {  
        "name":"Charlie",
        "age":20,
        "address":{  
          "country":"US",
          "state":"MA",
          "locality":"Boston"
        }
      }
    ]
  }
}

Lesen wir das in Python.

In [47]: j = json.loads(s)

In [54]: for student in j["class"]["students"]:
    print(student["name"])
   ....:     
Alice
Bob
Charlie

Es ist in Ordnung, weil jeder "Name" hat, aber wenn ich versuche, Statusinformationen zu erhalten, weil ich Statusinformationen möchte, hat Bob keine Statusinformationen und Alice hat überhaupt nicht den Schlüssel selbst "Adresse". Hmm.

In [55]: for student in j["class"]["students"]:
    print(student["address"]["state"])
   ....:
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-55-69836c86e040> in <module>()
      1 for student in j["class"]["students"]:
----> 2     print(student["address"]["state"])
      3 

KeyError: 'address'

Sie können den Standardwert mit "dict.get (key, default_val)" angeben, er ist jedoch redundant, da er in mehreren Stufen verschachtelt ist. Mit zunehmender Tiefe wird es immer schwieriger.

Es ist also "defaultdict". json.load und json.loads haben einen Port namens object_hook, der die Hook-Verarbeitung für das Diktat des Decodierungsergebnisses angibt. Verwenden wir ihn also. Python ist eine wunderbare Sprache, um eine solche API zu haben. 18.2. Dokumentation zu Json - JSON Encoder und Decoder - Python 2.7ja1

Definieren Sie die folgende Methode

def _hook(d):
    return collections.defaultdict(_factory, d)

Übergeben Sie es an object_hook in json.loads.

In [75]: j2 = json.loads(s, object_hook=_hook)
In [83]: for student in j2["class"]["students"]:
   ....:     print(student["address"]["state"])
   ....:     
defaultdict(<function _factory at 0x10a57ccf8>, {})
defaultdict(<function _factory at 0x10a57ccf8>, {})
MA

Erledigt. KeyErrror tritt nicht auf. Es ist ein wenig schwierig zu benutzen, so wie es ist, also werde ich es durch eine Hilfsmethode für die Konvertierung geben. Ich habe es möglich gemacht, einen zu verwendenden alternativen Wert anzugeben, und der alternative Standardwert ist die Zeichenfolge "default_state".

In [91]: def _dd(v, alt_val="default_state"):
    return alt_val if isinstance(v, collections.defaultdict) and len(v) == 0 else v
   ....: 

In [92]: for student in j2["class"]["students"]:
    print(_dd(student["address"]["state"]))
   ....:     
default_state
default_state
MA

Jetzt können Sie den Standardwert mit einer kleinen Menge an Beschreibung angeben, unabhängig davon, wo sich der fehlende Schlüssel befindet. Wenn es sich tatsächlich um den letzten Anruf handelt (dh das Anruf-Timing bei "student [" address "] [" state "]" anstelle von "student [" address "]" im obigen Code, wird der Standardwert zurückgegeben. Ich wollte, aber ich gab auf, weil ich nicht feststellen konnte, ob es der letzte Anruf war. Wenn Sie wissen, wie es geht, lassen Sie es mich bitte wissen.

das ist alles.

Recommended Posts

Erstellen Sie ein Standarddikt, das ein Standarddikt zurückgibt, um eine Welt zu erstellen, in der KeyErrror nicht auftritt (+ JSON-Parsing-Beispiel).
Tornado - Erstellen wir eine Web-API, die JSON problemlos mit JSON zurückgibt
Python-Spezialcodec, der zu wissen scheint, aber nicht weiß
So beheben Sie einen Fehler, bei dem das Jupyter-Notebook nicht automatisch gestartet wird
Ich habe versucht, eine Klasse zu erstellen, mit der Json in Python problemlos serialisiert werden kann
Eine Geschichte, die manchmal nicht funktioniert, wenn pip die neueste ist
Ich habe versucht, ein Wörterbuch ohne Berücksichtigung der Groß- und Kleinschreibung zu erstellen
So erstellen Sie eine JSON-Datei in Python