Wie würden Sie überprüfen, ob eine Variable ein Wörterbuch in Python ist?
Ich möchte beispielsweise, dass die Werte im Wörterbuch durchlaufen werden, bis ein Wörterbuch gefunden wird. Führen Sie dann eine Schleife durch die gefundene:
dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}
for k, v in dict.iteritems():
if ###check if v is a dictionary:
for k, v in v.iteritems():
print(k, ' ', v)
else:
print(k, ' ', v)
python
dictionary
Riley
quelle
quelle
isinstance(v, collections.abc.Mapping)
. Mit anderen Worten, dies ist kein genaues Duplikat von "Unterschiede zwischen isinstance () und type ()".Antworten:
Sie könnten verwenden
if type(ele) is dict
oder verwenden,isinstance(ele, dict)
was funktionieren würde, wenn Sie eine Unterklasse hättendict
:quelle
isinstance(ele, collections.Mapping)
. Es funktioniert fürdict()
,collections.OrderedDict()
undcollections.UserDict()
. Das Beispiel in der Frage ist spezifisch genug, damit Padriacs Antwort funktioniert, aber es ist nicht gut genug für den allgemeinen Fall.ele.items()
warum überprüfen Sie den Typ? EAFP / Ente-Eingabe funktioniert hier, wickeln nurfor k,v in ele.items()
intry...except (AttributeError, TypeError)
. Wenn eine Ausnahmeele
items
items()
Methode 2. hatte, die zufällig eine iterable ergab, und 3. wobei jedes Element dieser iterable als 2 dargestellt werden kann -Tupel. Zu diesem Zeitpunkt hat Ihr benutzerdefiniertes Objekt bereits ein halbes Diktat implementiert. Für die Zwecke des aufgelisteten Codes haben wir uns nur um die bedingte Erweiterung des verschachtelten Elements gekümmert, und Ihr benutzerdefiniertes Objekt implementiert dies bereits. (Es ist ein bisschen ironisch, dass Sie @Alexander Ryzhovs Kommentar als zu allgemein kritisieren, aber jetzt einen allgemeinen Fallitems()
, die eine verschachtelte Iterierbarkeit ergeben).collections.abc.Mapping
, könnte ein Hinweis angebracht sein , dass sie das gleiche sind, abercollections.abc
nicht verfügbar ist, bevor Python 3.3.collections.Mapping
Alias ist in Python 3.6 noch verfügbar, aber nicht dokumentiert, daher sollte man es wahrscheinlich vorziehencollections.abc.Maping
.Das OP hat die Startvariable nicht ausgeschlossen. Der Vollständigkeit halber wird hier der allgemeine Fall der Verarbeitung eines vermeintlichen Wörterbuchs behandelt, das Elemente als Wörterbücher enthalten kann.
Befolgen Sie auch die von Python (3.8) empfohlene Methode zum Testen des Wörterbuchs in den obigen Kommentaren.
quelle
dict.iteritems()
existiert nicht in Python 3, sollten Siedict.items()
stattdessen verwenden.Dies ist eine ausgezeichnete Frage, aber es ist bedauerlich, dass die am besten bewertete Antwort mit einer schlechten Empfehlung führt
type(obj) is dict
.(Beachten Sie, dass Sie auch keinen
dict
Variablennamen verwenden sollten - es ist der Name des eingebauten Objekts.)Wenn Sie Code schreiben, der von anderen importiert und verwendet wird, gehen Sie nicht davon aus, dass sie das eingebaute Diktat direkt verwenden. Diese Annahme macht Ihren Code unflexibler und in diesem Fall leicht versteckte Fehler, die das Programm nicht fehlerhaft machen würden .
Ich empfehle dringend, aus Gründen der Korrektheit, Wartbarkeit und Flexibilität für zukünftige Benutzer niemals weniger flexible, unidiomatische Ausdrücke in Ihrem Code zu haben, wenn es flexiblere, idiomatische Ausdrücke gibt.
is
ist ein Test für die Objektidentität . Es unterstützt keine Vererbung, keine Abstraktion und keine Schnittstelle.Daher werde ich verschiedene Optionen bereitstellen, die dies tun.
Unterstützende Vererbung:
Dies ist die erste Empfehlung , die ich machen würde, denn es ermöglicht es Benutzern , ihre eigene Unterklasse von dict zu versorgen, oder eine
OrderedDict
,defaultdict
oderCounter
aus den Sammlungen Modul:if isinstance(any_object, dict):
Es gibt aber noch flexiblere Möglichkeiten.
Unterstützende Abstraktionen:
Auf diese Weise kann der Benutzer Ihres Codes eine eigene benutzerdefinierte Implementierung einer abstrakten Zuordnung verwenden, die auch eine Unterklasse von enthält
dict
, und dennoch das richtige Verhalten erhalten.Verwenden Sie die Schnittstelle
Sie hören häufig den OOP-Rat "Programmieren auf eine Schnittstelle".
Diese Strategie nutzt Pythons Polymorphismus oder Ententypisierung.
Versuchen Sie also einfach, auf die Schnittstelle zuzugreifen und die spezifischen erwarteten Fehler (
AttributeError
falls es keine gibt.items
undTypeError
falls sieitems
nicht aufrufbar sind) mit einem vernünftigen Fallback abzufangen - und jetzt gibt Ihnen jede Klasse, die diese Schnittstelle implementiert, ihre Elemente (Anmerkung.iteritems()
ist in Python weg) 3):Vielleicht denken Sie, dass die Verwendung von Enten-Typisierung zu weit geht, um zu viele Fehlalarme zuzulassen, und dies kann abhängig von Ihren Zielen für diesen Code der Fall sein.
Fazit
Nicht verwenden
is
, um Typen auf Standardkontrollfluss zu überprüfen. Verwenden Sieisinstance
, berücksichtigen Sie Abstraktionen wieMapping
oderMutableMapping
und vermeiden Sie die Typprüfung insgesamt, indem Sie die Schnittstelle direkt verwenden.quelle