347 Stimmen

Was ist der beste (idiomatische) Weg, um den Typ einer Python-Variablen zu überprüfen?

Ich muss wissen, ob eine Variable in Python eine Zeichenkette oder ein Diktat ist. Ist an dem folgenden Code etwas falsch?

if type(x) == type(str()):
    do_something_with_a_string(x)
elif type(x) == type(dict()):
    do_somethting_with_a_dict(x)
else:
    raise ValueError

Update : Ich habe die Antwort von avisser akzeptiert (obwohl ich meine Meinung ändern werde, wenn jemand erklärt, warum isinstance ist vorzuziehen gegenüber type(x) is ).

Aber danke an nakedfanatic, der mich daran erinnert hat, dass es oft sauberer ist, ein dict (als Fallanweisung) als eine if/elif/else-Reihe zu verwenden.

Lassen Sie mich meinen Anwendungsfall näher erläutern. Wenn eine Variable eine Zeichenkette ist, muss ich sie in eine Liste aufnehmen. Wenn es ein Diktat ist, brauche ich eine Liste der eindeutigen Werte. Hier ist, was ich kam mit:

def value_list(x):
    cases = {str: lambda t: [t],
             dict: lambda t: list(set(t.values()))}
    try:
        return cases[type(x)](x)
    except KeyError:
        return None

Si isinstance bevorzugt wird, wie würden Sie das schreiben value_list() Funktion?

345voto

Suraj Punkte 4649

Was passiert, wenn jemand eine Unicode-Zeichenkette an Ihre Funktion übergibt? Oder eine von dict abgeleitete Klasse? Oder eine Klasse, die eine dict-ähnliche Schnittstelle implementiert? Der folgende Code deckt die ersten beiden Fälle ab. Wenn Sie Python 2.6 verwenden, sollten Sie vielleicht collections.Mapping anstelle von dict gemäß der ABC PEP .

def value_list(x):
    if isinstance(x, dict):
        return list(set(x.values()))
    elif isinstance(x, basestring):
        return [x]
    else:
        return None

63voto

type(dict()) sagt: "Erstelle ein neues Diktat und finde dann heraus, was sein Typ ist". Es ist schneller, einfach zu sagen dict . Wenn Sie aber nur den Typ überprüfen wollen, ist eine idiomatischere Methode isinstance(x, dict) .

Beachten Sie, dass isinstance umfasst auch Unterklassen (dank Dustin ):

class D(dict):
    pass

d = D()
print("type(d) is dict", type(d) is dict)  # -> False
print("isinstance (d, dict)", isinstance(d, dict))  # -> True

46voto

Albert Visser Punkte 1124

Eingebaute Typen in Python haben eingebaute Namen:

>>> s = "hallo"
>>> type(s) is str
True
>>> s = {}
>>> type(s) is dict
True

Übrigens: Beachten Sie die ist Betreiber. Die Typprüfung (wenn man sie so nennen will) erfolgt jedoch in der Regel durch die Einbettung eines typspezifischen Tests in eine try-except-Klausel, da es nicht so sehr auf den Typ der Variablen ankommt, sondern darauf, ob man etwas Bestimmtes mit ihr tun kann oder nicht.

23voto

Dirk Stoop Punkte 3070

Isinstance ist Type vorzuziehen, weil es auch als True ausgewertet wird, wenn Sie eine Objektinstanz mit ihrer Superklasse vergleichen, was im Grunde bedeutet, dass Sie niemals Ihren alten Code für die Verwendung mit dict- oder str-Subklassen speziell kodieren müssen.

Zum Beispiel:

 >>> class a_dict(dict):
 ...     pass
 ... 
 >>> type(a_dict()) == type(dict())
 False
 >>> isinstance(a_dict(), dict)
 True
 >>> 

Natürlich kann es Situationen geben, in denen Sie dieses Verhalten nicht wünschen, aber diese sind - hoffentlich - viel seltener als Situationen, in denen Sie es wünschen.

8voto

JV. Punkte 2530

Ich denke, ich werde mich für den Ansatz des Enten-Tippens entscheiden - "wenn es wie eine Ente läuft und wie eine Ente quakt, ist es eine Ente". Auf diese Weise müssen Sie sich nicht darum kümmern, ob die Zeichenfolge ein Unicode oder Ascii ist.

Ich werde Folgendes tun:

In [53]: s='somestring'

In [54]: u=u'someunicodestring'

In [55]: d={}

In [56]: for each in s,u,d:
    if hasattr(each, 'keys'):
        print list(set(each.values()))
    elif hasattr(each, 'lower'):
        print [each]
    else:
        print "error"
   ....:         
   ....:         
['somestring']
[u'someunicodestring']
[]

Die Experten hier können sich gerne zu dieser Art der Verwendung von Ducktyping äußern. Ich habe es bereits verwendet, aber erst kürzlich das genaue Konzept dahinter kennengelernt und bin sehr begeistert davon. So würde ich gerne wissen, ob das ist ein Overkill zu tun.

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