Frage Bestimmen Sie den Typ eines Objekts?


Gibt es eine einfache Möglichkeit festzustellen, ob eine Variable eine Liste, ein Wörterbuch oder etwas anderes ist? Ich bekomme ein Objekt zurück, das entweder ein Typ sein kann, und ich muss in der Lage sein, den Unterschied zu erkennen.


1378
2018-02-08 21:37


Ursprung


Antworten:


Um den Typ eines Objekts zu erhalten, können Sie das integrierte Objekt verwenden type() Funktion. Wenn Sie ein Objekt als einzigen Parameter übergeben, wird das Typobjekt dieses Objekts zurückgegeben:

>>> type([]) is list
True
>>> type({}) is dict
True
>>> type('') is str
True
>>> type(0) is int
True
>>> type({})
<type 'dict'>
>>> type([])
<type 'list'>

Dies funktioniert natürlich auch für benutzerdefinierte Typen:

>>> class Test1 (object):
        pass
>>> class Test2 (Test1):
        pass
>>> a = Test1()
>>> b = Test2()
>>> type(a) is Test1
True
>>> type(b) is Test2
True

Beachten Sie, dass type() gibt nur den unmittelbaren Typ des Objekts zurück, kann aber nicht über die Typvererbung informieren.

>>> type(b) is Test1
False

Um das abzudecken, sollten Sie die isinstance Funktion. Dies funktioniert natürlich auch für eingebaute Typen:

>>> isinstance(b, Test1)
True
>>> isinstance(b, Test2)
True
>>> isinstance(a, Test1)
True
>>> isinstance(a, Test2)
False
>>> isinstance([], list)
True
>>> isinstance({}, dict)
True

isinstance() ist normalerweise der bevorzugte Weg, um den Typ eines Objekts zu sichern, da es auch abgeleitete Typen akzeptiert. Wenn Sie das Typobjekt (aus welchen Gründen auch immer) nicht benötigen, verwenden Sie isinstance() ist gegenüber bevorzugt type().

Der zweite Parameter von isinstance() akzeptiert auch ein Tupel von Typen, so dass es möglich ist, gleichzeitig nach mehreren Typen zu suchen. isinstance gibt dann true zurück, wenn das Objekt einen der folgenden Typen aufweist:

>>> isinstance([], (tuple, list, set))
True

1603
2018-02-08 21:40



Sie können das tun mit type():

>>> a = []
>>> type(a)
<type 'list'>
>>> f = ()
>>> type(f)
<type 'tuple'>

141
2018-02-08 21:39



Es könnte mehr Pythonic sein, ein zu verwenden try...except Block. Wenn Sie also eine Klasse haben, die wie eine Liste quatscht oder wie ein Diktat quakt, wird sie sich unabhängig von ihrem Typ korrekt verhalten Ja wirklich ist.

Um zu verdeutlichen, ist die bevorzugte Methode, "den Unterschied zwischen Variablenarten zu erkennen", etwas genanntes Ente tippen: Solange die Methoden (und die Rückgabetypen), auf die eine Variable reagiert, das sind, was Ihre Subroutine erwartet, behandeln Sie sie so, wie Sie es erwarten. Zum Beispiel, wenn Sie eine Klasse haben, die die Klammeroperatoren mit überlädt getattr und setattr, aber verwendet ein lustiges internes Schema, es wäre angemessen, sich wie ein Wörterbuch zu verhalten, wenn es das ist, was es zu emulieren versucht.

Das andere Problem mit dem type(A) is type(B) Überprüfung ist, dass wenn A ist eine Unterklasse von Bbewertet es false wenn du programmatisch hoffst, dass es so wäre true. Wenn ein Objekt eine Unterklasse einer Liste ist, sollte es wie eine Liste funktionieren: Wenn Sie den Typ wie in der anderen Antwort dargestellt überprüfen, wird dies verhindert. (isinstance wird aber funktionieren).


37
2018-02-08 21:43



Auf Instanzen des Objekts haben Sie auch:

__class__

Attribut. Hier ist ein Beispiel aus der Python 3.3-Konsole

>>> str = "str"
>>> str.__class__
<class 'str'>
>>> i = 2
>>> i.__class__
<class 'int'>
>>> class Test():
...     pass
...
>>> a = Test()
>>> a.__class__
<class '__main__.Test'>

Beachten Sie, dass in Python 3.x und in New-Style-Klassen (optional erhältlich in Python 2.6) Klasse und Typ zusammengeführt wurden, was manchmal zu unerwarteten Ergebnissen führen kann. Hauptsächlich aus diesem Grund ist meine bevorzugte Art, Typen / Klassen zu testen, die isinstanz eingebaute Funktion.


30
2018-06-26 21:38



Ermitteln Sie den Typ eines Python-Objekts

Ermitteln Sie den Typ eines Objekts mit type

>>> obj = object()
>>> type(obj)
<class 'object'>

Obwohl es funktioniert, vermeiden Sie doppelte Unterstriche wie __class__ - Sie sind nicht semantisch öffentlich, und obwohl in diesem Fall vielleicht nicht, haben die eingebauten Funktionen normalerweise ein besseres Verhalten.

>>> obj.__class__ # avoid this!
<class 'object'>

Typprüfung

Gibt es eine einfache Möglichkeit festzustellen, ob eine Variable eine Liste, ein Wörterbuch oder etwas anderes ist? Ich bekomme ein Objekt zurück, das entweder ein Typ sein kann, und ich muss in der Lage sein, den Unterschied zu erkennen.

Nun, das ist eine andere Frage, benutze keinen Typ - benutze es isinstance:

def foo(obj):
    """given a string with items separated by spaces, 
    or a list or tuple, 
    do something sensible
    """
    if isinstance(obj, str):
        obj = str.split()
    return _foo_handles_only_lists_or_tuples(obj)

Dies deckt den Fall ab, in dem Ihr Benutzer durch Subclassing etwas Cleveres oder Vernünftiges unternimmt str - Nach dem Prinzip der Liskov-Substitution möchten Sie Subklassen-Instanzen verwenden können, ohne Ihren Code zu brechen - und isinstance unterstützt dies.

Verwende Abstraktionen

Noch besser, Sie können nach einer bestimmten abstrakten Basisklasse suchen collections oder numbers:

from collections import Iterable
from numbers import Number

def bar(obj):
    """does something sensible with an iterable of numbers, 
    or just one number
    """
    if isinstance(obj, Number): # make it a 1-tuple
        obj = (obj,)
    if not isinstance(obj, Iterable):
        raise TypeError('obj must be either a number or iterable of numbers')
    return _bar_sensible_with_iterable(obj)

Oder einfach nicht explizit Typ-check

Oder, am besten, verwenden Sie die Enttippung und überprüfen Sie Ihren Code nicht explizit. Duck-Typing unterstützt Likov Substitution mit mehr Eleganz und weniger Ausführlichkeit.

def baz(obj):
    """given an obj, a dict (or anything with an .items method) 
    do something sensible with each key-value pair
    """
    for key, value in obj.items():
        _baz_something_sensible(key, value)

Fazit

  • Benutzen type um die Klasse einer Instanz zu erhalten.
  • Benutzen isinstance um explizit nach tatsächlichen Unterklassen oder registrierten Abstraktionen zu suchen.
  • Und vermeiden Sie einfach die Überprüfung, wo es Sinn macht.

14
2018-03-14 21:12



Sie können verwenden type() oder isinstance().

>>> type([]) is list
True

Sei gewarnt, dass du klatschen kannst list oder einen anderen Typ, indem Sie eine Variable im aktuellen Bereich desselben Namens zuweisen.

>>> the_d = {}
>>> t = lambda x: "aight" if type(x) is dict else "NOPE"
>>> t(the_d) 'aight'
>>> dict = "dude."
>>> t(the_d) 'NOPE'

Oben sehen wir das dict Wird einem String zugewiesen, daher der Test:

type({}) is dict

... scheitert.

Um dies zu umgehen und zu verwenden type() vorsichtiger:

>>> import __builtin__
>>> the_d = {}
>>> type({}) is dict
True
>>> dict =""
>>> type({}) is dict
False
>>> type({}) is __builtin__.dict
True

10
2018-05-31 21:57



Während die Fragen ziemlich alt sind, stolperte ich darüber, während ich selbst einen richtigen Weg fand, und ich denke, es muss noch geklärt werden, zumindest für Python 2.x (habe nicht nach Python 3 gesucht, aber da das Problem bei klassischen Klassen auftaucht, die bei einer solchen Version weg sind, spielt es wahrscheinlich keine Rolle).

Hier versuche ich die Frage des Titels zu beantworten: Wie kann ich den Typ eines beliebigen Objekts bestimmen?? Andere Vorschläge zur Verwendung oder Nichtbenutzung sind in vielen Kommentaren und Antworten in Ordnung, aber ich gehe nicht auf diese Bedenken ein.

Das Hauptproblem mit der type() Ansatz ist das Es funktioniert nicht ordnungsgemäß mit alten Instanzen:

class One:
    pass

class Two:
    pass


o = One()
t = Two()

o_type = type(o)
t_type = type(t)

print "Are o and t instances of the same class?", o_type is t_type

Die Ausführung dieses Snippets würde Folgendes ergeben:

Are o and t instances of the same class? True

Was, so argumentiere ich, ist nicht das, was die meisten Menschen erwarten würden.

Das __class__ Annäherung ist der Genauigkeit am nächsten, aber es wird nicht in einem entscheidenden Fall funktionieren: wenn das übergebene Objekt ein alter Stil ist Klasse (keine Instanz!), da diesen Objekten ein solches Attribut fehlt.

Dies ist der kleinste Codeschnipsel, den ich mir vorstellen kann, der eine solche berechtigte Frage in konsistenter Weise erfüllt:

#!/usr/bin/env python
from types import ClassType
#we adopt the null object pattern in the (unlikely) case
#that __class__ is None for some strange reason
_NO_CLASS=object()
def get_object_type(obj):
    obj_type = getattr(obj, "__class__", _NO_CLASS)
    if obj_type is not _NO_CLASS:
        return obj_type
    # AFAIK the only situation where this happens is an old-style class
    obj_type = type(obj)
    if obj_type is not ClassType:
        raise ValueError("Could not determine object '{}' type.".format(obj_type))
    return obj_type

4
2018-06-17 08:35