Wie überprüft man in Python, ob eine Variable ein Wörterbuch ist?
Dies ist eine ausgezeichnete Frage, aber es ist bedauerlich, dass die am meisten hochgestufte Antwort mit einer schlechten Empfehlung beginnt, type(obj) is dict
.
(Beachten Sie, dass Sie auch nicht dict
als Variablennamen verwenden sollten - es ist der Name des integrierten Objekts.)
Wenn Sie Code schreiben, der importiert und von anderen verwendet wird, gehen Sie nicht davon aus, dass sie das integrierte Wörterbuch direkt verwenden - diese Annahme macht Ihren Code unflexibler und führt in diesem Fall zu leicht versteckten Fehlern, die das Programm nicht abbrechen lassen würden.
Ich schlage dringend vor, aus Gründen der Korrektheit, Wartbarkeit und Flexibilität für zukünftige Benutzer niemals weniger flexible, unidiomatische Ausdrücke in Ihrem Code zu verwenden, wenn es flexiblere, idiomatische Ausdrücke gibt.
is
ist ein Test für Objektidentität. Er unterstützt keine Vererbung, er unterstützt keine Abstraktion und er unterstützt nicht die Schnittstelle.
Also werde ich mehrere Optionen anbieten, die das tun.
Vererbung unterstützen:
Dies ist die erste Empfehlung, die ich machen würde, weil es Benutzern ermöglicht, ihre eigene Unterklasse von dict, oder ein OrderedDict
, defaultdict
, oder Counter
aus dem Collections-Modul bereitzustellen:
if isinstance(any_object, dict):
Aber es gibt noch flexiblere Optionen.
Abstraktionen unterstützen:
from collections.abc import Mapping
if isinstance(any_object, Mapping):
Dies erlaubt es dem Benutzer Ihres Codes, ihre eigene benutzerdefinierte Implementierung eines abstrakten Mappings zu verwenden, das auch jede Unterklasse von dict
einschließt, und trotzdem das korrekte Verhalten liefert.
Die Schnittstelle verwenden
Man hört oft den OOP-Rat, "zur Schnittstelle programmieren".
Diese Strategie nutzt die Polymorphie oder Duck-Typing von Python.
Versuchen Sie also einfach, auf die Schnittstelle zuzugreifen, fangen Sie die spezifisch erwarteten Fehler ab (AttributeError
falls es kein .items
gibt und TypeError
falls items
nicht aufrufbar ist) mit einem sinnvollen Fallback - und jetzt wird jede Klasse, die diese Schnittstelle implementiert, Ihnen ihre Elemente geben (beachten Sie, dass .iteritems()
in Python 3 entfernt wurde):
try:
items = any_object.items()
except (AttributeError, TypeError):
non_items_behavior(any_object)
else: # no exception raised
for item in items: ...
Vielleicht halten Sie die Verwendung von Duck-Typing auf diese Weise für zu weitgehend, da sie zu viele falsche Positive zulässt, und das kann je nach Ihren Zielen für diesen Code sein.
Schlussfolgerung
Verwenden Sie is
nicht zur Überprüfung von Typen für die Standardsteuerung. Verwenden Sie isinstance
, betrachten Sie Abstraktionen wie Mapping
oder MutableMapping
, und erwägen Sie das Vermeiden von Typüberprüfungen insgesamt, indem Sie die Schnittstelle direkt verwenden.