Frage

Was ist der beste Weg, um zu überprüfen, ob ein bestimmtes Objekt eines bestimmten Typs ist? Wie sei es zu prüfen, ob das Objekt von einem bestimmten Typ erbt?

Lassen Sie uns sagen, ich habe ein Objekt o. Wie kann ich überprüfen, ob es sich um eine str ist?

War es hilfreich?

Lösung

Um zu überprüfen, ob o eine Instanz von str ist oder eine Unterklasse von str, verwenden Sie isinstance (dies würde die "kanonische" Art und Weise sein):

if isinstance(o, str):

Um zu überprüfen, ob die Art der o genau str (schließen Unterklassen):

if type(o) is str:

Die folgenden funktioniert auch, und kann in einigen Fällen nützlich sein:

if issubclass(type(o), str):

Siehe Eingebaute Funktionen in dem Python Library Reference für relevante Informationen.

Noch eine Anmerkung: In diesem Fall, wenn Sie mit Python 2, können Sie tatsächlich verwenden möchten:

if isinstance(o, basestring):

da dies fangen auch Unicode-Strings ( unicode ist kein Unterklasse von str, beide str und unicode sind Subklassen von basestring ). Beachten Sie, dass basestring nicht mehr existiert in Python 3, wo es eine strikte Trennung von Strings ( bytes ).

Alternativ akzeptiert isinstance ein Tupel von Klassen. Dies wird wieder wahr, wenn x eine Instanz einer beliebigen Unterklasse von einem der Punkte (str, Unicode):

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

Andere Tipps

die meisten Pythonic Weg, um den Typ eines Objekts zu überprüfen, ist ... nicht zu überprüfen.

Da Python Duck Typing ermutigt, sollten Sie nur try...except die Methoden des Objekts, wie Sie verwenden möchten benutze sie. Also, wenn Ihre Funktion ist für ein beschreibbares Dateiobjekt suchen, nicht überprüfen, ob es eine Unterklasse von file ist, nur versuchen, seine .write() Methode zu verwenden!

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

isinstance(o, str) wird True zurück, wenn o ein str ist oder von einem Typ ist, der von str erbt.

type(o) is str kehrt True, wenn und nur wenn o ein str. Es wird wieder False wenn o von einem Typ ist, der von str erbt.

Nachdem die Frage gestellt und beantwortet wurde, Type Hints wurden Python hinzugefügt . Typ Hinweise in Python erlauben Typen, aber in einer ganz anderen Art und Weise von statisch typisierten Sprachen überprüft werden. Geben Sie Hinweise in Python die erwarteten Typen von Argumenten mit Funktionen wie Laufzeit zugänglichen Daten assoziieren mit Funktionen zugeordnet und diese können für Typen geprüft werden. Beispiel Typen Hinweis Syntax:

def foo(i: int):
    return i

foo(5)
foo('oops')

In diesem Fall wollen wir ein Fehler für foo('oops') ausgelöst werden, da die kommentierte Typ des Arguments int ist. Der Mehr Typ Hinweis nicht Ursache ein Fehler auftreten, wenn das Skript normal ausgeführt wird. Allerdings fügt Attribute auf die Funktion der erwarteten Typen beschreiben, dass andere Programme abfragen und verwenden für Typ Fehler zu überprüfen.

Eine dieser anderen Programme, die verwendet werden können, die Art Fehler zu finden ist mypy:

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

(Möglicherweise müssen mypy von Ihrem Paketmanager installieren. Ich glaube nicht, es mit CPython kommt aber scheint ein gewisses Maß an „officialness“ zu haben.)

Geben Sie auf diese Weise die Überprüfung unterscheidet sich von Typ Überprüfung eingegeben statisch kompilierten Sprachen. Da Typen dynamisch sind in Python, Typprüfung muss zur Laufzeit erfolgen, was ein Kosten erlegt - auch auf korrekte Programmen - wenn wir, dass es bei jeder Gelegenheit passieren bestehen. Explizite Typprüfungen auch restriktiver als erforderlich sein können und unnötige Fehler verursachen (z ist das Argument muss wirklich genau der sein list Typ oder ist etwas iterable ausreichend?).

Der Vorteil der expliziten Typprüfung ist, dass es Fehler früher zu fangen und gibt klarere Fehlermeldungen als Ente eingeben. Die genauen Anforderungen einer Ente Typ kann nur mit externer Dokumentation ausgedrückt werden (hoffentlich ist es gründlich und genau) und Fehler von inkompatible Typen auftreten können weit von wo sie stammen.

Pythons Typ Hinweise sollen einen Kompromiss anzubieten, wo Typen festgelegt werden können und überprüft, aber es gibt keine zusätzliche Kosten während der üblichen Codeausführung.

Das typing Paket bietet Variablen eingeben, die in Art verwendet werden können Hinweise auf benötigtes Verhalten auszudrücken, ohne bestimmte Typen zu erfordern. Zum Beispiel enthält es Variablen wie Iterable und Callable für Hinweise auf die Notwendigkeit für jede Art mit diesen Verhaltensweisen zu spezifizieren.

Während Typ Hinweise die Pythonic Art und Weise sind Arten zu überprüfen, ist es oft noch mehr Pythonic Typen überhaupt nicht zu überprüfen und sich auf Ente eingeben. Type Hints sind relativ neu und die Jury ist noch heraus, wenn sie die Pythonic Lösung. Ein relativ unumstritten, aber sehr allgemein Vergleich: Typ Hinweise geben eine Form der Dokumentation, die durchgesetzt werden können, Code früher und leichter zu erzeugen erlauben Fehler zu verstehen, Fehler zu fangen, die Ente eingeben kann nicht, und kann statisch überprüft werden (in einem ungewöhnlichen Sinn, aber es ist immer noch außerhalb der Laufzeit). Auf der anderen Seite hat die Ente eingeben Pythonic Weg für eine lange Zeit, ist der kognitiven Aufwand für statische Typisierung nicht aufzwingen, ist weniger ausführlich, und alle lebensfähigen Arten akzeptieren und dann einige.

Hier ist ein Beispiel, warum Ente eingeben, ohne zu wissen böse ist, wenn es gefährlich ist. Zum Beispiel: Hier wird der Python-Code ist (möglicherweise richtiges Einrücken Weglassen), beachten Sie, dass diese Situation ist vermeidbar durch von isinstance und issubclassof Funktionen kümmert sich um sicherzustellen, dass, wenn Sie wirklich eine Ente benötigen, brauchen Sie nicht eine Bombe bekommen.

class Bomb:
    def __init__(self):
        ""

    def talk(self):
        self.explode()

    def explode(self):
        print "BOOM!, The bomb explodes."

class Duck:
    def __init__(self):
        ""
    def talk(self):
        print "I am a duck, I will not blow up if you ask me to talk."    

class Kid:
    kids_duck = None

    def __init__(self):
        print "Kid comes around a corner and asks you for money so he could buy a duck."

    def takeDuck(self, duck):
        self.kids_duck = duck
        print "The kid accepts the duck, and happily skips along"

    def doYourThing(self):
        print "The kid tries to get the duck to talk"
        self.kids_duck.talk()

myKid = Kid()
myBomb = Bomb()
myKid.takeDuck(myBomb)
myKid.doYourThing()
isinstance(o, str)

Link docs

Ich denke, die kühle Sache über eine dynamische Sprache wie Python ist sollten Sie wirklich so etwas nicht überprüfen müssen.

Ich würde rufen Sie einfach die erforderlichen Methoden auf dem Objekt und ein AttributeError fangen. Später dies ermöglicht es Ihnen, Ihre Methoden mit anderen (scheinbar unzusammenhängenden) zu nennen Objekte verschiedene Aufgaben, wie spöttische ein Objekt für die Prüfung zu erreichen.

Ich habe das viel verwendet wird, wenn Daten aus dem Web mit urllib2.urlopen() bekommen, die gibt eine Datei wie Objekt. Dies kann wiederum kann zu fast jede Methode übergeben werden, die aus einer Datei liest, weil es die gleiche read() Methode als eine echte Datei implementiert.

Aber ich bin sicher, es gibt eine Zeit und Ort für isinstance() verwenden, sonst wäre es wahrscheinlich nicht da sein:)

Um Hugo:

Du meinst wahrscheinlich list statt array, aber das weist auf das ganze Problem mit Typprüfung - Sie wollen nicht wissen, ob das betreffende Objekt eine Liste ist, wollen Sie wissen, ob es irgendeine Art von Sequenz ist oder wenn es ist ein einzelnes Objekt. Also versuchen Sie es wie eine Sequenz zu verwenden.

Sagen Sie das Objekt zu einer vorhandenen Sequenz hinzugefügt werden sollen, oder wenn es eine Folge von Objekten, füge sie alle

try:
   my_sequence.extend(o)
except TypeError:
  my_sequence.append(o)

Ein Trick dabei ist, wenn Sie mit Streichern und / oder Sequenzen von Strings arbeiten - das ist heikel, als ein String oft als ein einziges Objekt gedacht wird, aber es ist auch eine Folge von Zeichen. Schlimmer als das, wie es ist wirklich eine Folge von Einzelzeichenfolgen der Länge.

ich wähle in der Regel meine API so zu gestalten, dass es akzeptiert nur entweder einen einzelnen Wert oder eine Sequenz - es macht die Dinge einfacher. Es ist nicht schwer, einen [ ] um den einzigen Wert zu setzen, wenn Sie es passieren, wenn nötig.

(Obwohl diese Fehler mit Zeichenketten verursachen können, wie sie aussehen kann (sind) Sequenzen.)

Für komplexere Art Validierungen Ich mag typeguard den Ansatz der Validierung anhand von Python-Typ Hinweis Anmerkungen :

from typeguard import check_type
from typing import List

try:
    check_type('mylist', [1, 2], List[int])
except TypeError as e:
    print(e)

Sie können in sehr sauber und gut lesbare Art und Weise sehr komplexe Validierungen durchführen.

check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo) 

Sie können mit der folgenden Zeile überprüfen, um zu überprüfen, welche Zeichen den gegebenen Wert geben ist:

def chr_type(chrx):
    if chrx.isalpha()==True:
        return 'alpha'
    elif chrx.isdigit()==True:
        return 'numeric'
    else:
        return 'nothing'

chr_type("12)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top