Woher wissen, ob eine Variable ein Tupel, eine Zeichenfolge oder eine Ganzzahl ist?

78

Ich versuche, eine Typinkongruenz herauszufinden, während ich einer Zeichenfolge in einer Verkettungsoperation eine Zeichenfolge hinzufüge.

Grundsätzlich ist der zurückgegebene Fehler a TypeError(kann Zeichenfolge und Tupel nicht verketten); Daher möchte ich herausfinden, wo ich einen Wert als Tupel anstelle eines Strings zugewiesen habe.

Alle Werte, die ich zuweise, sind Zeichenfolgen. Ich muss also herausfinden, woher das Tupel kommt. Ich hatte gehofft, dass es in Python eine Möglichkeit gibt, herauszufinden, was in einer Variablen enthalten ist und welcher Typ es ist.

Bisher konnte ich mit pdb den Inhalt der Variablen überprüfen und die erwarteten Werte korrekt erhalten. Ich möchte aber auch den Typ der Variablen kennen (wenn der Compiler logischerweise einen Typfehler auslösen kann, bedeutet dies, dass er weiß, was sich in einer Variablen befindet und ob er mit der auszuführenden Operation kompatibel ist muss ein Weg sein, um diesen Wert / Flag herauszuholen).

Gibt es eine Möglichkeit, den Typ einer Variablen in Python auszudrucken?

Übrigens habe ich versucht, alle meine Variablen so zu ändern, dass sie explizit Zeichenfolgen sind, aber es ist nicht möglich, sie zu erzwingen str (myvar). Daher kann ich nicht überall, wo ich Zeichenfolgen verwende, einfach als Zeichenfolgentyp umwandeln.


quelle
2
Ich möchte nicht wählerisch sein, aber Variablen haben in Python niemals einen Typ, sondern nur Objekte (auf die durch Variablen verwiesen wird). Aus diesem Grund gibt es keine echten Typumwandlungen, sondern nur Objektkonvertierungsfunktionen.
Jürgen Strobel
In der Tat Jürgen; Ich weiß nicht genau, wie Python unter der Haube funktioniert, aber ich gehe davon aus, dass dies eine objektorientierte Sprache ist. Wenn ich also eine Variable erstelle, wird ein Objekt des richtigen Datentyps erstellt und mit einem Zeiger darauf verwiesen Variable Ich verwende tatsächlich eine Instanz der Objektzeichenfolge (oder einen anderen Datentyp). Der Endpunkt ist, den Typ dieses Objekts zu erhalten :)

Antworten:

41

Sie verwenden nur:

type(varname)

welches int, str, float, etc ausgibt ...

Gabriel Ross
quelle
Die Verwendung __class__ist fast immer besser als die Verwendung, typeda sie in den meisten Situationen dasselbe zurückgeben, außer dass typeder Typ aller Klassen im alten Stil als "Instanz" deklariert wird. beziehen Sie sich auf diese SO-Frage
Darren Yin
@DarrenYin Es ist nicht wahr, dass type(o)und o.__class__ immer das gleiche zurückgeben. Die am häufigsten gestellte Antwort in der verknüpften Frage besagt, dass sie nicht vorhanden war, als Sie sie verknüpft haben. Zusätzlich typeerfordert weniger tippen und sieht aus wie öffentliche API - Funktion (keine Unterstrichen).
WloHu
173
isinstance(obj, tuple)
isinstance(obj, basestring)
isinstance(obj, int)
Nicolae Dascalu
quelle
danke für die Antwort; Dies ist ideal für eine Überprüfung während der Ausführung des Programms, aber ich versuche, den Wert beim Debuggen mit pdb zu erhalten. Dies ist ein guter Weg, um das Problem zu vermeiden!
27

isinstance nutzen?

if isinstance(var, int):

if isinstance(var, str):

if isinstance(var, tuple):
Drake Guan
quelle
Das Testen auf strschlägt bei unicodeZeichenfolgen fehl . Außerdem isinstance(var, tuple)werden alle Variablen übersehen, die zufällig lists sind, was in solchen Situationen häufig auftritt. Natürlich möchten Sie möglicherweise einen Fehler machen, wenn die Variable eine Instanz von a ist list, aber es ist gut sicherzustellen, dass Sie wissen, was in verschiedenen Situationen passieren wird.
Darren Yin
4
In Python 3 können Sie eine Folge von Typen verwenden, um zu testen:isinstance(var, (tuple, list))
bugmenot123
Komisch, dass der andere alle Upvotes bekommt, obwohl du zuerst geantwortet hast.
qwerty_so
10

Bitte beachten Sie, dass das Konstrukt if type(varname) == "tuple":nicht funktioniert , wenn Sie Ihren var-Typ in der if-Anweisung einchecken möchten . Aber diese werden:

if type(varname) is tuple:
if type(varname) is list:
if type(varname) is dict:
if type(varname) is int:
if type(varname) is str:
Goujon
quelle
4
Sie sollten stattdessen wirklich isinstance verwenden. type () ist gefährlich, wenn es um Vererbung geht.
Bugmenot123
@ bugmenot123, ich decke nicht alle möglichen Ergebnisse ab, ich notiere den Fehler, den die Leute normalerweise machen, wenn sie versuchen, nach Typ zu suchen, und wurde dann überrascht, wenn es nicht funktioniert. Ansonsten hast du absolut recht.
Goujon
Ich hoffe, es macht Ihnen nichts aus, aber ich habe Ihre Antwort in meiner eigenen referenziert und mit einer anderen Methodik kontert. Wenn Sie etwas dagegen haben, werde ich den Verweis entfernen. Vielen Dank.
WinEunuuchs2Unix
@ WinEunuuchs2Unix, Obwohl es meiner Meinung nach keine andere Methode ist, 'is' durch '==' zu ersetzen, macht es mir überhaupt nichts aus.
Goujon
4

Sie möchten wahrscheinlich (unter der Annahme von Python 2.x) mit testen isinstance(obj, basestring). Sie haben die Möglichkeiten der Verwendung isinstance, typeund rufen Sie das Attribut __class__, sondern isinstanceist wahrscheinlich diejenige , die Sie hier haben wollen. In diesem Artikel finden Sie eine ausführlichere Beschreibung der Unterschiede zwischen den drei Optionen.

Darren Yin
quelle
Danke Darren; Ich werde die Tests wahrscheinlich mit Ihrem Vorschlag durchführen, aber im Moment verwende ich pdb; So kann ich herausfinden, welches die problematische Variable ist, und vermeiden, denselben Fehler zu machen (ich mag defensive Codierung, aber gleichzeitig ziehe ich es vor, zunächst einen Fehler zu vermeiden, anstatt mich auf eine Prüfung zu verlassen, um einen möglichen Fehler zu finden Fehler). Interessant, dass es auch das Klassenattribut gibt ; habe nie davon gehört.
1

repr (Objekt) gibt eine Textbeschreibung des Objekts, die Typ und Wert anzeigen sollte. Sie können dies im Debugger drucken oder anzeigen.

Bei einfachen Werten gibt repr normalerweise dieselbe Zeichenfolge zurück, als würden Sie den Wert buchstäblich in Code schreiben. Für benutzerdefinierte Klassen gibt es den Klassennamen und die Objekt-ID oder etwas anderes an, wenn die Klasse es ist

__repr__

wird überschrieben.

Jürgen Strobel
quelle
Danke für die Antwort Jürgen. Ich habe versucht, repr, aber es gibt mir den Wert der Variablen * zurück (in meinem Fall die Zeichenfolge), also macht es dasselbe wie p (varname) ... mache ich etwas falsch, da ich sehen sollte, wie Sie erwähnt haben, tippe, Wert und Beschreibung des Objekts?
1
Nein. Es gibt ein String-Literal für einen Str oder Unicode zurück, einschließlich der Anführungszeichen. Sie sollten es also als diesen Typ erkennen. Es gibt nicht zitierte Ziffern für ganzzahlige Typen und ähnliche für andere numerische Typen zurück. Für eine benutzerdefinierte Klasse A wird standardmäßig so etwas wie <mymodule.A-Instanz bei 0x123456> zurückgegeben, aber einige Klassen überschreiben diese Beschreibungszeichenfolge.
Jürgen Strobel
-2

Um Goujons Antwort zu ergänzen , betrachten Sie diese Liste gemischter Ganzzahlen und Tupel:

for f in fills:
    print (type(f), f)
    if type(f)==int : print "INTEGER!!!"

Erzeugt diese Ausgabe:

(<type 'int'>, 0)
INTEGER!!!
(<type 'tuple'>, (62973, 39058, 25708, 102))
(<type 'int'>, 1)
INTEGER!!!
(<type 'tuple'>, (16968, 12069, 3329, 102))
(<type 'int'>, 2)
INTEGER!!!
(<type 'tuple'>, (24939, 62205, 30062, 102))
(<type 'tuple'>, (32911, 32911, 0, 153))
(<type 'tuple'>, (32911, 0, 0, 153))
(<type 'tuple'>, (32911, 0, 32911, 153))
(<type 'tuple'>, (65535, 0, 0, 153))
(<type 'tuple'>, (0, 0, 65535, 153))
(<type 'tuple'>, (0, 32911, 0, 153))
(<type 'tuple'>, (0, 65535, 65535, 153))

Das Geheimnis besteht also nicht darin, auf "int"Zeichenfolgen zu testen , sondern intstattdessen auf Schlüsselwörter. Wenn Sie wie ich sind und aus der Bash-Skriptwelt migrieren, ist die Verwendung von ==Tests in der Python-Skriptwelt wahrscheinlich Ihr erster Schritt.

WinEunuuchs2Unix
quelle
1
Sie haben Goujons Antwort nicht richtig gelesen. Sie schrieben speziell "das Konstrukt if type (varname) ==" tuple ": funktioniert nicht" und erklärten dann den richtigen Weg.
Kaya3
@ kaya3 In meiner Antwort habe ich versucht zu sagen, wenn Sie die "doppelten Anführungszeichen entfernt haben, wird es funktionieren.
WinEunuuchs2Unix
2
Ich habe verstanden, was Sie in Ihrer Antwort geschrieben haben. es ist falsch, weil Sie sagen, dass Goujons Antwort diesen Fehler gemacht hat, obwohl Goujons Antwort tatsächlich feststellte, dass es ein Fehler ist . Ihr Fix ist der gleiche wie der, den Goujon als Lösung für dieses Problem geschrieben hat.
Kaya3
@ kaya3 Ich habe die Antwort umformuliert und erklärt, warum ==es Leuten wie mir wichtig ist. Ist es jetzt ok?
WinEunuuchs2Unix
1
Ihre Antwort ist nicht mehr falsch, aber es ist nicht klar, was Sie zu der vorhandenen Antwort hinzugefügt haben, außer dass Sie sie verwenden können, ==anstatt iswenn Sie möchten. Es gibt keinen praktischen Unterschied, außer in sehr seltenen Randfällen, und in diesen Fällen isist die richtige Wahl.
Kaya3