415 Stimmen

Wie überprüft man, ob eine Variable in Python ein Wörterbuch ist?

Wie würdest du überprüfen, ob eine Variable in Python ein Wörterbuch ist?

Zum Beispiel möchte ich, dass es durch die Werte im Wörterbuch geht, bis es ein Wörterbuch findet. Dann durch das gefundene Wörterbuch gehen:

dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}

for k, v in dict.items():
    if ###überprüfen, ob v ein Wörterbuch ist:
        for k, v in v.iteritems():
            print(k, ' ', v)
    else:
        print(k, ' ', v)

487voto

Padraic Cunningham Punkte 168356

Verwenden Sie isinstance(ele, dict), das true für dict-Objekte sowie Unterklassen von dict wie OrderedDict und defaultdict zurückgibt:

d = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}
for element in d.values():
    if isinstance(element, dict):
       for k, v in element.items():
           print(k, ' ', v)

Sie können if type(ele) is dict verwenden, wenn Sie ausschließlich Instanzen von dict prüfen möchten und nicht Unterklassen davon, obwohl dies im Allgemeinen nicht empfohlen wird.

106voto

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.

8voto

David Punkte 142

In Python 3.6

    typeVariable = type(variable)

    print('Vergleich', typeVariable == dict)

    if typeVariable == dict:
        #'wahr'
    else:
        #'falsch'

6voto

CodeMantle Punkte 1359

Der OP hat die Startvariable nicht ausgeschlossen, daher hier zur Vollständigkeit, wie man mit dem generischen Fall umgeht, eine vermeintliche Dictionary zu verarbeiten, das möglicherweise Einträge als Dictionary enthält.

Auch empfehle ich die Verwendung der reinen Python (3.8) empfohlenen Methode zum Testen auf Dictionary in den obigen Kommentaren.

from collections.abc import Mapping

my_dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}

def parse_dict(in_dict): 
    if isinstance(in_dict, Mapping):
        for k_outer, v_outer in in_dict.items():
            if isinstance(v_outer, Mapping):
                for k_inner, v_inner in v_outer.items():
                    print(k_inner, v_inner)
            else:
                print(k_outer, v_outer)

parse_dict(my_dict)

5voto

Cam Punkte 879

Meine Tests haben ergeben, dass dies funktioniert, wenn wir jetzt Typenhinweise haben:

from typing import Dict

if isinstance(my_dict, Dict):
    # True
else:
    # False

Übrigens, einige Diskussionen über typing.Dict hier

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X