Dieser Artikel bietet Ihnen eine detaillierte Erklärung (Codebeispiel) von defaultdict in Python. Ich hoffe, dass er Ihnen als Referenz dienen wird.
Standardwerte können sehr praktisch sein
Wie wir alle wissen, kommt es in Python zu einer KeyError-Ausnahme, wenn Sie auf einen Schlüssel zugreifen, der nicht im Wörterbuch vorhanden ist wird ausgelöst (in JavaScript wird undefiniert zurückgegeben, wenn ein bestimmter Schlüssel nicht im Objektattribut vorhanden ist). Manchmal ist es jedoch sehr praktisch, für jeden Schlüssel im Wörterbuch einen Standardwert zu haben. Zum Beispiel das folgende Beispiel:
strings = ('puppy', 'kitten', 'puppy', 'puppy', 'weasel', 'puppy', 'kitten', 'puppy') counts = {} for kw in strings: counts[kw] += 1
Dieses Beispiel zählt, wie oft ein Wort in Zeichenfolgen vorkommt, und zeichnet es im Zählwörterbuch auf. Jedes Mal, wenn ein Wort erscheint, wird der im Schlüssel gespeicherte Wert entsprechend counts um 1 erhöht. Tatsächlich wird beim Ausführen dieses Codes eine KeyError-Ausnahme ausgelöst, wenn jedes Wort zum ersten Mal gezählt wird. Da es in Pythons Diktat keinen Standardwert gibt, kann dies in der Python-Befehlszeile überprüft werden:
>>> counts = dict() >>> counts {} >>> counts['puppy'] += 1 Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'puppy'
strings = ('puppy', 'kitten', 'puppy', 'puppy', 'weasel', 'puppy', 'kitten', 'puppy') counts = {} for kw in strings: if kw not in counts: counts[kw] = 1 else: counts[kw] += 1 # counts: # {'puppy': 5, 'weasel': 1, 'kitten': 2}
Sie können den Standardwert auch über die Methode dict.setdefault() festlegen:
strings = ('puppy', 'kitten', 'puppy', 'puppy', 'weasel', 'puppy', 'kitten', 'puppy') counts = {} for kw in strings: counts.setdefault(kw, 0) counts[kw] += 1
Die Methode dict.setdefault() empfängt zwei Parameter. Der erste Parameter ist der Name des Schlüssels und der zweite Parameter ist der Standardwert. Wenn der angegebene Schlüssel nicht im Wörterbuch vorhanden ist, wird der im Parameter angegebene Standardwert zurückgegeben. Andernfalls wird der im Wörterbuch gespeicherte Wert zurückgegeben. Der Code in der for-Schleife kann mithilfe des Rückgabewerts der Methode dict.setdefault() umgeschrieben werden, um ihn prägnanter zu gestalten:
strings = ('puppy', 'kitten', 'puppy', 'puppy', 'weasel', 'puppy', 'kitten', 'puppy') counts = {} for kw in strings: counts[kw] = counts.setdefault(kw, 0) + 1
Die defaultdict-Klasse ähnelt einem Diktat, wird jedoch mit einem Typ initialisiert:
>>> from collections import defaultdict >>> dd = defaultdict(list) >>> dd defaultdict(<type 'list'>, {})
Die Initialisierungsfunktion der defaultdict-Klasse akzeptiert einen Typ als Parameter und kann instanziiert werden, wenn der Schlüssel, auf den zugegriffen wird, dies tut nicht vorhanden Ändern Sie einen Wert als Standardwert:
>>> dd['foo'] [] >>> dd defaultdict(<type 'list'>, {'foo': []}) >>> dd['bar'].append('quux') >>> dd defaultdict(<type 'list'>, {'foo': [], 'bar': ['quux']})
Es ist zu beachten, dass diese Form des Standardwerts nur gültig ist, wenn auf dict[key]
oder dict.__getitem__(key)
zugegriffen wird. Die Gründe dafür werden im Folgenden vorgestellt.
>>> from collections import defaultdict >>> dd = defaultdict(list) >>> 'something' in dd False >>> dd.pop('something') Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'pop(): dictionary is empty' >>> dd.get('something') >>> dd['something'] []
Diese Klasse akzeptiert nicht nur den Typnamen als Parameter der Initialisierungsfunktion, sondern kann auch jede aufrufbare Funktion ohne Parameter verwenden. Zu diesem Zeitpunkt wird das Rückgabeergebnis der Funktion als Standardwert verwendet , wodurch die Standardwerte flexibler werden. Im Folgenden wird anhand eines Beispiels veranschaulicht, wie die benutzerdefinierte Funktion null () ohne Parameter als Parameter der Initialisierungsfunktion verwendet wird:
>>> from collections import defaultdict >>> def zero(): ... return 0 ... >>> dd = defaultdict(zero) >>> dd defaultdict(<function zero at 0xb7ed2684>, {}) >>> dd['foo'] 0 >>> dd defaultdict(<function zero at 0xb7ed2684>, {'foo': 0})
Verwenden Sie collections.defaultdict
, um das anfängliche Wortzählproblem zu lösen. Der Code lautet wie folgt :
from collections import defaultdict strings = ('puppy', 'kitten', 'puppy', 'puppy', 'weasel', 'puppy', 'kitten', 'puppy') counts = defaultdict(lambda: 0) # 使用lambda来定义简单的函数 for s in strings: counts[s] += 1
Durch den obigen Inhalt müssen Sie die Verwendung der Defaultdict-Klasse verstanden haben. Wie implementiert man also die Standardwertfunktion in der Defaultdict-Klasse? Der Schlüssel dazu ist die Verwendung der Methode __missing__():
>>> from collections import defaultdict >>> print defaultdict.__missing__.__doc__ __missing__(key) # Called by __getitem__ for missing key; pseudo-code: if self.default_factory is None: raise KeyError(key) self[key] = value = self.default_factory() return value
Wenn wir uns den Dokumentstring der Methode __missing__() ansehen, können wir sehen, dass wir die Methode __getitem__() verwenden, um auf ein nicht vorhandenes Objekt zuzugreifen key (Die Form dict[key] ist eigentlich eine vereinfachte Form der Methode __getitem__()), die die Methode __missing__() aufruft, um den Standardwert abzurufen und den Schlüssel zum Wörterbuch hinzuzufügen.
Eine ausführliche Einführung in die Methode __missing__() finden Sie im Abschnitt „Mapping Types – dict“ in der offiziellen Python-Dokumentation.
Ab Version 2.5 im Dokument eingeführt: Wenn eine von dict abgeleitete Unterklasse die Methode __missing__() definiert, ruft dict[key] beim Zugriff auf einen nicht vorhandenen Schlüssel die Methode __missing__() auf, um sie abzurufen Standardwert.
Daraus ist ersichtlich, dass dict zwar die Methode __missing__() unterstützt, diese Methode jedoch nicht in dict selbst vorhanden ist. Stattdessen muss diese Methode in der abgeleiteten Unterklasse implementiert werden. Dies kann leicht überprüft werden:
>>> print dict.__missing__.__doc__ Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: type object 'dict' has no attribute '__missing__'
Gleichzeitig können wir weitere Experimente durchführen, eine Unterklasse Missing definieren und die Methode __missing__() implementieren:
>>> class Missing(dict): ... def __missing__(self, key): ... return 'missing' ... >>> d = Missing() >>> d {} >>> d['foo'] 'missing' >>> d {}
Das Rückgabeergebnis spiegelt __missing__( ) wider. Methode funktioniert. Auf dieser Basis modifizieren wir die Methode __missing__() leicht, sodass diese Unterklasse einen Standardwert für nicht vorhandene Schlüssel wie die Klasse defautldict festlegt:
>>> class Defaulting(dict): ... def __missing__(self, key): ... self[key] = 'default' ... return 'default' ... >>> d = Defaulting() >>> d {} >>> d['foo'] 'default' >>> d {'foo': 'default'}
Zuerst muss die Methode __getitem__() die Methode __missing__() aufrufen, wenn der Zugriffsschlüssel fehlschlägt:
class defaultdict(dict): def __getitem__(self, key): try: return dict.__getitem__(self, key) except KeyError: return self.__missing__(key)
Zweitens muss die Methode __missing__()
implementiert werden, um den Standardwert festzulegen:
class defaultdict(dict): def __getitem__(self, key): try: return dict.__getitem__(self, key) except KeyError: return self.__missing__(key) def __missing__(self, key): self[key] = value = self.default_factory() return value
Dann muss die Initialisierungsfunktion __init__()
der Defaultdict-Klasse Typ- oder aufrufbare Funktionsparameter akzeptieren:
class defaultdict(dict): def __init__(self, default_factory=None, *a, **kw): dict.__init__(self, *a, **kw) self.default_factory = default_factory def __getitem__(self, key): try: return dict.__getitem__(self, key) except KeyError: return self.__missing__(key) def __missing__(self, key): self[key] = value = self.default_factory() return value
最后,综合以上内容,通过以下方式完成兼容新旧Python版本的代码:
try: from collections import defaultdictexcept ImportError: class defaultdict(dict): def __init__(self, default_factory=None, *a, **kw): dict.__init__(self, *a, **kw) self.default_factory = default_factory def __getitem__(self, key): try: return dict.__getitem__(self, key) except KeyError: return self.__missing__(key) def __missing__(self, key): self[key] = value = self.default_factory() return value
Das obige ist der detaillierte Inhalt vonAusführliche Erklärung von defaultdict in Python (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!