Die meisten Dinge, die jeder liebt, sind vorbereitet und interessant.
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
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>, {})
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