1822 Stimmen

Was ist der kanonische Weg, um für Typ in Python zu überprüfen?

Wie prüfe ich, ob ein Objekt von einem bestimmten Typ ist oder ob es von einem bestimmten Typ erbt?

Wie kann ich überprüfen, ob das Objekt o ist vom Typ str ?

16 Stimmen

Ich glaube, Herr Coombs übersieht Beispiele wie nicht-JSON serialisierbare Klassen. Wenn man einen großen Datenblock durch eine Funktion schickt (deren Code man nicht beeinflussen kann), möchte man vielleicht bestimmte Teile dieser Daten in ein <str> konvertieren, bevor man sie weitergibt. Zumindest ist das so I landete auf dieser Seite...

7 Stimmen

Es scheint, dass der häufigste Grund für diese Frage darin besteht, dass man zwischen Zeichenketten und Iterablen von Zeichenketten unterscheiden möchte. Dies ist eine knifflige Frage, weil Strings sind Iterabilen von Zeichenketten - eine Ein-Zeichen-Zeichenkette ist sogar eine Folge von sich selbst (als ich das letzte Mal nachgesehen habe - man sollte sich wahrscheinlich nicht darauf verlassen). Aber würde jemand jemals Verwendung für etwas String-ähnliches haben? Oui . Die Antwort auf die Frage "Wie unterscheide ich zwischen Zeichenketten und anderen Iterabilen von Zeichenketten?" ist also richtig: "Das hängt davon ab, was Sie tun wollen" :-D

7 Stimmen

Python-Typ-Annotationen sind jetzt eine Sache. Werfen Sie einen Blick auf mypy

2141voto

Fredrik Johansson Punkte 22430

Utilice isinstance um zu prüfen, ob o ist eine Instanz von str oder einer Unterklasse von str :

if isinstance(o, str):

Um zu prüfen, ob der Typ der o ist genau str , mit Ausnahme der Unterklassen von str :

if type(o) is str:

Eine weitere Alternative zu den oben genannten Möglichkeiten:

if issubclass(type(o), str):

Ver Eingebaute Funktionen in der Python Library Reference für relevante Informationen.


Überprüfung von Zeichenketten in Python 2

Für Python 2 ist dies ein besserer Weg, um zu prüfen, ob o ist eine Zeichenkette:

if isinstance(o, basestring):

weil dadurch auch Unicode-Zeichenfolgen erfasst werden. unicode ist nicht eine Unterklasse von str in der Erwägung, dass beide str y unicode sind Unterklassen von basestring . In Python 3, basestring nicht mehr existiert, da es eine eine strikte Trennung von Zeichenketten ( str ) und binäre Daten ( bytes ).

Alternativ dazu, isinstance akzeptiert ein Tupel von Klassen. Dies wird zurückgegeben True si o eine Instanz einer beliebigen Unterklasse einer der folgenden Klassen ist (str, unicode) :

if isinstance(o, (str, unicode)):

33 Stimmen

Str.__subclasses__() gibt nur die direkten Unterklassen von str zurück und tut nicht dasselbe wie issubclass() oder isinstance(). (Um das zu tun, müssten Sie rekursiv .__subclasses__() aufrufen.

18 Stimmen

Das ist eine gute Antwort, aber ich denke, sie sollte wirklich mit einer Warnung beginnen, dass Sie dies normalerweise nicht in Python tun sollten. So wie es ist, scheint es die Annahme zu bestätigen, dass dies eine "kanonische Sache in Python zu tun" ist, die es nicht ist.

6 Stimmen

Was ist der Unterschied zwischen "Instanz" und "genau"? Wenn type(a) is Object ist es dann nicht auch wahr, dass isinstance(a, Object) . Wenn jedoch type(a) is SubClassOfObject dann type(a) is Object == False pero isinstance(a, Object) == True . Oder?

268voto

Dan Lenski Punkte 72055

El Die meisten Der pythonische Weg, den Typ eines Objekts zu prüfen, ist... ihn nicht zu prüfen.

Da Python ermutigt Duck Typing sollten Sie einfach try...except um die Methoden des Objekts so zu verwenden, wie Sie sie verwenden wollen. Wenn Ihre Funktion also nach einem beschreibbaren Dateiobjekt sucht, nicht prüfen, ob es sich um eine Unterklasse von file versuchen Sie einfach, seine .write() Methode!

Natürlich brechen diese schönen Abstraktionen manchmal zusammen und isinstance(obj, cls) ist das, was Sie brauchen. Aber gehen Sie sparsam damit um.

96 Stimmen

Meiner Meinung nach ist der pythonischste Weg, mit jedem Argument zurechtzukommen, das gegeben wird. In meinem Code kann ich oft nicht wissen, ob ich ein Objekt oder ein Array von Objekten erhalte, und ich verwende intern eine Typüberprüfung, um ein einzelnes Objekt in eine Liste mit einem Element zu konvertieren.

16 Stimmen

Anstatt nur zu versuchen, seine Write-Methode zu verwenden, gibt es Zeiten, in denen Sie dies tun möchten, ohne eine Ausnahme zu verursachen. In diesem Fall könnten Sie tun... if hasattr(ob, "write") and callable(ob.write): Oder sparen Sie sich den Zugang zu einem Diktat... func = getattr(ob, "write", None) if callable(func): ...

170 Stimmen

Duck typing ist über mit eine Bibliothek. Bei der Typprüfung geht es um Schreiben eine Bibliothek. Nicht derselbe Problembereich.

80voto

Herge Punkte 18189

isinstance(o, str) wird zurückgegeben True si o ist ein str oder von einem Typ ist, der von str .

type(o) is str wird zurückgegeben True wenn und nur wenn o ist eine str. Es wird zurückgegeben False si o ist von einem Typ, der erbt von str .

9 Stimmen

Natürlich schlägt dies fehl, wenn das Objekt nicht eine Instanz von "str" ist, sondern von etwas, das einer Zeichenkette ähnelt. Wie Unicode, mmap, UserString oder ein anderer benutzerdefinierter Typ. Der übliche Ansatz in Python ist es, keine Typüberprüfungen durchzuführen.

2 Stimmen

Dies ist sehr hilfreich. Denn der Unterschied zwischen isinstance y type(var) == type('') ist nicht klar.

50voto

SuperNova Punkte 20412

En Python 3.10 können Sie verwenden | en isinstance :

>>> isinstance('1223', int | str) 
True

>>> isinstance('abcd', int | str) 
True

8 Stimmen

Das ist cool und so... aber ich sehe nicht wirklich, was das hier hinzufügt oder wie es wirklich hilfreich ist.

1 Stimmen

Eine der großartigen Eigenschaften von Python ist, dass es keine zufälligen Symbole überall im Code gibt. Leider verschwindet diese Eigenschaft langsam mit der Zeit.

44voto

Praxeolitic Punkte 19598

Nachdem die Frage gestellt und beantwortet wurde, Typ-Hinweise wurden zu Python hinzugefügt . Typhinweise in Python ermöglichen die Überprüfung von Typen, aber auf eine ganz andere Weise als bei statisch typisierten Sprachen. Typ-Hinweise in Python assoziieren die erwarteten Typen von Argumenten mit Funktionen als zur Laufzeit zugängliche Daten, die mit Funktionen verbunden sind, und dies ermöglicht für zu prüfende Typen. Beispiel für die Syntax eines Typhinweises:

def foo(i: int):
    return i

foo(5)
foo('oops')

In diesem Fall soll ein Fehler ausgelöst werden bei foo('oops') da der annotierte Typ des Arguments int . Der hinzugefügte Typ-Hinweis bedeutet nicht verursachen ein Fehler auftritt, wenn das Skript normal ausgeführt wird. Es fügt der Funktion jedoch Attribute hinzu, die die erwarteten Typen beschreiben, die andere Programme abfragen und zur Prüfung auf Typfehler verwenden können.

Eines dieser anderen Programme, die zum Auffinden des Typfehlers verwendet werden können, ist mypy :

mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"

(Möglicherweise müssen Sie die mypy von Ihrem Paketmanager. Ich glaube nicht, dass es mit CPython kommt, aber scheint ein gewisses Maß an "Offizialität" zu haben).

Die Typüberprüfung auf diese Weise unterscheidet sich von der Typüberprüfung in statisch typisierten kompilierten Sprachen. Da die Typen in Python dynamisch sind, muss die Typprüfung zur Laufzeit durchgeführt werden, was Kosten verursacht - sogar für korrekte Programme - wenn wir darauf bestehen, dass dies bei jeder Gelegenheit geschieht. Explizite Typüberprüfungen können auch restriktiver sein als nötig und unnötige Fehler verursachen (z.B. muss das Argument wirklich genau list Typs oder ist irgendetwas Iterierbares ausreichend?).

Der Vorteil der expliziten Typprüfung besteht darin, dass sie Fehler früher erkennen und klarere Fehlermeldungen ausgeben kann als die Duck-Typisierung. Die genauen Anforderungen eines Duck-Typs können nur mit externer Dokumentation ausgedrückt werden (die hoffentlich gründlich und genau ist), und Fehler aufgrund inkompatibler Typen können weit entfernt vom Ursprungsort auftreten.

Pythons Typ-Hinweise sollen einen Kompromiss bieten, bei dem Typen angegeben und überprüft werden können, aber keine zusätzlichen Kosten bei der normalen Codeausführung entstehen.

El typing Paket bietet Typvariablen, die in Typhinweisen verwendet werden können, um benötigte Verhaltensweisen auszudrücken, ohne dass bestimmte Typen erforderlich sind. Zum Beispiel enthält es Variablen wie Iterable y Callable für Hinweise auf die Notwendigkeit eines Typs mit diesen Verhaltensweisen.

Während Typhinweise der pythonischste Weg sind, Typen zu prüfen, ist es oft noch pythonischer, Typen überhaupt nicht zu prüfen und sich auf Duck Typing zu verlassen. Typhinweise sind relativ neu, und es ist noch nicht klar, wann sie die beste pythonische Lösung sind. Ein relativ unumstrittener, aber sehr allgemeiner Vergleich: Typ-Hinweise bieten eine Form der Dokumentation, die erzwungen werden kann, ermöglichen es, dass Code früher und leichter zu verstehen Fehler generiert, können Fehler abfangen, die Duck-Typing nicht kann, und können statisch überprüft werden (in einem ungewöhnlichen Sinn, aber es ist immer noch außerhalb der Laufzeit). Auf der anderen Seite ist Duck-Typing seit langem der Weg von Pythonic, erzwingt nicht den kognitiven Overhead der statischen Typisierung, ist weniger langatmig und akzeptiert alle brauchbaren Typen und noch einige mehr.

4 Stimmen

-1: mypy bezeichnet sich ausdrücklich als "statische Typüberprüfung", daher bin ich mir nicht sicher, woher Sie die Aussage "Typüberprüfung muss zur Laufzeit erfolgen" haben.

0 Stimmen

@Kevin Im Nachhinein war das eine unnötige Abschweifung, aber um mehr darüber zu erfahren, werden Pythons Typ-Hinweise in Laufzeitdaten umgewandelt und mypy ist ein Python-Modul, das die importlib um auf diese Daten zuzugreifen. Ob dies eine "statische Typüberprüfung" ist, ist eine philosophische Frage, aber es ist anders als die meisten erwarten würden, da der normale Sprachinterpreter und die Importmaschinerie beteiligt sind.

11 Stimmen

Auch das ist nicht wahr. Es verwendet typed_ast, die selbst ist nur ein Klon von ast mit zusätzlichen Funktionen. ast importiert keine Module, sondern zerlegt sie in einen abstrakten Syntaxbaum.

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