Wie überprüfe ich, ob eine Variable eine Klasse ist oder nicht?


236

Ich habe mich gefragt, wie ich überprüfen soll, ob eine Variable eine Klasse ist (keine Instanz!).

Ich habe versucht, die Funktion isinstance(object, class_or_type_or_tuple)zu verwenden, aber ich weiß nicht, welchen Typ eine Klasse haben würde.

Zum Beispiel im folgenden Code

class Foo: pass  
isinstance(Foo, **???**) # i want to make this return True.

Ich habe versucht, " class" durch ??? zu ersetzen. , aber mir wurde klar, dass dies classein Schlüsselwort in Python ist.

Antworten:


334

Noch besser: Verwenden Sie die inspect.isclassFunktion.

>>> import inspect
>>> class X(object):
...     pass
... 
>>> inspect.isclass(X)
True

>>> x = X()
>>> isinstance(x, X)
True
>>> y = 25
>>> isinstance(y, X)
False

7
Wenn Sie auch zurückkehren möchten inspect.isclass, Truewenn das zu untersuchende Objekt eine Klasseninstanz ist , verwenden Sieinspect.isclass(type(Myclass()))
michaelmeyer

8
Besser als was :)?
Mad Physicist

8
@michaelmeyer gibt type(whatever)immer ein Objekt zurück, das eine Klasse ist, daher ist diese Prüfung redundant. Wenn dies nicht der Fall wäre, gäbe es keine Möglichkeit zur Instanziierung, whateverund daher könnten Sie die Prüfung überhaupt nicht durchführen.
a_guest

Funktioniert bei mir nicht Wenn Sie python3 mit snakemake verwenden, type(snakemake.utils)kehren Sie zurück <class 'module'>und inspect.isclass(snakemake.utils)kehren dennoch zurück False.
Tedtoal

3
Das snakemake.utilliegt daran, dass ein Modul keine Klasse ist?
Benjamin Peterson

44

Die inspect.isclass ist wahrscheinlich die beste Lösung, und es ist wirklich leicht zu erkennen, wie sie tatsächlich implementiert ist

def isclass(object):
    """Return true if the object is a class.

    Class objects provide these attributes:
        __doc__         documentation string
        __module__      name of module in which this class was defined"""
    return isinstance(object, (type, types.ClassType))

5
import types
Denken Sie

13
types.ClassTypewird in Python 3 nicht mehr benötigt (und wird entfernt).
Kawing-Chiu

Dies funktioniert überhaupt nicht mit neuen
Stilklassen

Das wurde dem Inspektionsmodul entnommen, daher bezweifle ich, dass es nicht funktioniert. Es ist einfach, zum Beispiel mit Python2.7 zu überprüfenIn [8]: class NewStyle(object): ...: pass ...: In [9]: isinstance(NewStyle, (type, types.ClassType)) Out[9]: True
andrea_crotti

Dies ist die Python 2-Implementierung, die Klassen im alten und neuen Stil verarbeiten muss. Python 3 vereinfacht dies zu isinstance(object, type). Beachten Sie, dass Objekte wie int, list, strusw. sind auch Klassen, so dass Sie nicht diese verwenden können , unterscheiden zwischen benutzerdefinierten Klassen definiert in Python und integrierten Klassen in C - Code definiert .
Martijn Pieters

39
>>> class X(object):
...     pass
... 
>>> type(X)
<type 'type'>
>>> isinstance(X,type)
True

1
Hm ... Schöne Antwort, aber wenn ich in meiner Foo-Klasse (Foo) tippe, heißt es <type 'classobj'> anstelle von <type 'type'>. Ich gehe davon aus, dass der Unterschied darin besteht, dass X vom Objekt erbt, Foo jedoch nicht. Gibt es einen anderen Unterschied, der sich daraus ergibt? Vielen Dank.
Jeeyoungk

6
Es funktioniert nicht für Klassen im alten Stil : 'class Old:pass' 'isinstance(Old, type) == False', aber inspect.isclass(Old) == True.
JFS

1
@jeeyoungk: Du gehst nicht "davon aus, dass der Unterschied von ... kommt", sondern liest das tatsächlich im Code. Eine Unterklasse von Objekten ("neuer Stil") hat die gewünschten Eigenschaften, genau das, was Sie hier sehen.
S.Lott

12
Hier ist der Hinweis: Da dies für Klassen neuen Stils funktioniert, verwenden Sie keine Klassen alten Stils. Es macht keinen Sinn, Klassen im alten Stil zu verwenden.
S.Lott

isinstance (e, f) E ist das instanziierte Objekt, F ist das Klassenobjekt.
Dexter

24
isinstance(X, type)

Geben Sie Trueif Xis class zurück und Falsewenn nicht.


3
Ich bekomme Falsch, auch wenn X eine Klasse ist.
Mads Skjern

6
Dies funktioniert nur für neue Stilklassen. Alte Klassen sind vom Typ 'classobj'. Wenn Sie also alte Stilklassen verwenden, können Sie Folgendes tun: Typen importieren isinstance (X, types.ClassType)
Charles L.

2
Dies scheint dasselbe zu sein wie das S. Lott's answer, das vier Jahre älter ist.
Ethan Furman

5

Diese Prüfung ist sowohl mit Python 2.x als auch mit Python 3.x kompatibel.

import six
isinstance(obj, six.class_types)

Dies ist im Grunde eine Wrapper-Funktion, die die gleiche Prüfung wie in der Antwort von andrea_crotti durchführt.

Beispiel:

>>> import datetime
>>> isinstance(datetime.date, six.class_types)
>>> True
>>> isinstance(datetime.date.min, six.class_types)
>>> False


1

inspect.isclassAm einfachsten ist es, wie in der am häufigsten bewerteten Antwort angegeben zu verwenden.
Die Implementierungsdetails finden Sie unter python2 inspect und python3 inspect .
für die Klasse im neuen Stil: isinstance(object, type)
für die Klasse im alten Stil: isinstance(object, types.ClassType)
em, für die Klasse im alten Stil types.ClassTypewird Folgendes verwendet : Hier ist der Code von types.py :

class _C:
    def _m(self): pass
ClassType = type(_C)

1

Benjamin Peterson hat Recht mit der Verwendung inspect.isclass()für diesen Job. Beachten Sie jedoch, dass Sie mit der integrierten Funktion issubclass testen können, ob ein ClassObjekt ein bestimmtes Classund damit implizit ein Objekt ist . Abhängig von Ihrem Anwendungsfall kann dies pythonischer sein.Class

from typing import Type, Any
def isclass(cl: Type[Any]):
    try:
        return issubclass(cl, cl)
    except TypeError:
        return False

Kann dann so verwendet werden:

>>> class X():
...     pass
... 
>>> isclass(X)
True
>>> isclass(X())
False

-2

Hier gibt es bereits einige funktionierende Lösungen, aber hier ist eine andere:

>>> import types
>>> class Dummy: pass
>>> type(Dummy) is types.ClassType
True

types.ClassTypewurde in Python 3
Beau Barker
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.