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?

7voto

Ed. Punkte 449

Ich denke, es wäre besser, wenn man tatsächlich

if isinstance(x, str):
    do_something_with_a_string(x)
elif isinstance(x, dict):
    do_somethting_with_a_dict(x)
else:
    raise ValueError

2 alternative Formulare, je nach Code ist das eine oder andere wahrscheinlich sogar besser als das. Die eine ist, nicht zu schauen, bevor man springt

try:
  one, two = tupleOrValue
except TypeError:
  one = tupleOrValue
  two = None

Der andere Ansatz stammt von Guido und ist eine Form der Funktionsüberladung, die den Code offener gestaltet.

http://www.artima.com/weblogs/viewpost.jsp?thread=155514

3voto

nakedfanatic Punkte 2898

Das sollte funktionieren - also nein, es gibt keinen Fehler in Ihrem Code. Allerdings könnte es auch mit einem Diktat gemacht werden:

{type(str()): do_something_with_a_string,
 type(dict()): do_something_with_a_dict}.get(type(x), errorhandler)()

Ein bisschen prägnanter und pythonischer, finden Sie nicht auch?


Bearbeiten. Befolgung Avissers Rat, der Code funktioniert auch so, und sieht schöner:

{str: do_something_with_a_string,
 dict: do_something_with_a_dict}.get(type(x), errorhandler)()

3voto

Paul Hildebrandt Punkte 2594

Vielleicht möchten Sie typecheck ausprobieren. http://pypi.python.org/pypi/typecheck

Modul zur Typüberprüfung für Python

Dieses Paket bietet leistungsfähige Laufzeit-Typüberprüfungsfunktionen für Python-Funktionen, -Methoden und -Generatoren. Ohne einen benutzerdefinierten Präprozessor oder Änderungen an der Sprache zu benötigen, ermöglicht das Typecheck-Paket Programmierern und Qualitätssicherungsingenieuren, präzise Aussagen über die Eingabe und Ausgabe ihres Codes zu treffen.

1voto

Matthew Schinckel Punkte 33617

Ich habe einen anderen Ansatz gewählt:

from inspect import getmro
if (type([]) in getmro(obj.__class__)):
    # This is a list, or a subclass of...
elif (type{}) in getmro(obj.__class__)):
    # This one is a dict, or ...

Ich weiß allerdings nicht mehr, warum ich dies anstelle von isinstance verwendet habe...

-2voto

nosklo Punkte 204121

*sigh*

Nein, eine Typüberprüfung der Argumente in Python ist nicht notwendig. Es ist niemals notwendig.

Wenn Ihr Code entweder eine Zeichenkette oder ein dict-Objekt akzeptiert, ist Ihr Entwurf fehlerhaft.

Das kommt daher, dass man, wenn man den Typ eines Objekts noch nicht kennt in Ihrem eigenen Programm nicht kennt, dann machen Sie bereits etwas falsch.

Die Typüberprüfung schadet der Wiederverwendung von Code und verringert die Leistung. Eine Funktion, die die je nach Typ des übergebenen Objekts unterschiedliche Aktionen ausführt, ist fehleranfällig und hat ein Verhalten, das schwerer zu verstehen und zu pflegen ist.

Sie haben die folgenden vernünftigeren Möglichkeiten:

1) Erstellen Sie eine Funktion unique_values die Dicts in eindeutige Listen von Werten umwandelt:

def unique_values(some_dict):
    return list(set(some_dict.values()))

Lassen Sie Ihre Funktion davon ausgehen, dass das übergebene Argument immer eine Liste ist. Wenn Sie also eine Zeichenkette an die Funktion übergeben müssen, tun Sie das einfach:

myfunction([some_string])

Wenn du ein Diktat abgeben musst, tust du das:

myfunction(unique_values(some_dict))

Das ist die beste Option, sie ist sauber, leicht zu verstehen und zu pflegen. Jeder jeder, der den Code liest, versteht sofort, was passiert, und Sie müssen nicht Typenprüfung durchführen.

2) Erstelle zwei Funktionen, eine, die Listen von Strings akzeptiert und eine, die Dicts akzeptiert. Sie können die eine Funktion die andere intern aufrufen lassen, und zwar auf die bequemste Weise Weise ( myfunction_dict kann eine Liste von Zeichenketten erstellen und die myfunction_list ).

Auf jeden Fall, nicht abtippen . Sie ist völlig unnötig und hat nur Schattenseiten. Refactor Ihren Code stattdessen in einer Weise, die Sie nicht brauchen, um die Typisierung zu überprüfen. Dies bringt Ihnen nur Vorteile, sowohl kurz- als auch langfristig.

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