¿Cómo verificar si una variable es una clase o no?

236

Me preguntaba cómo verificar si una variable es una clase (¡no una instancia!) O no.

Intenté usar la función isinstance(object, class_or_type_or_tuple)para hacer esto, pero no sé qué tipo tendría una clase.

Por ejemplo, en el siguiente código

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

Traté de sustituir " class" con ??? , pero me di cuenta de que classes una palabra clave en python.

jeeyoungk
fuente

Respuestas:

335

Aún mejor: usa la inspect.isclassfunción.

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

>>> x = X()
>>> isinstance(x, X)
True
>>> y = 25
>>> isinstance(y, X)
False
Benjamin Peterson
fuente
77
Si también desea inspect.isclassregresar Truesi el objeto a inspeccionar es una instancia de clase , useinspect.isclass(type(Myclass()))
michaelmeyer
8
¿Mejor que qué :)?
Mad Physicist
8
@michaelmeyer type(whatever)siempre devuelve un objeto que es una clase, por lo que esta comprobación es redundante. Si no fuera así, no habría forma de crear una instancia whatevery, por lo tanto, no podría realizar la verificación en primer lugar.
a_guest
No funciona para mi Usando python3 con snakemake, type(snakemake.utils)regresa <class 'module'>y aún inspect.isclass(snakemake.utils)regresa False.
tedtoal
3
¿Eso es porque snakemake.utilun módulo no es una clase?
Benjamin Peterson el
44

Inspect.isclass es probablemente la mejor solución, y es realmente fácil ver cómo se implementa realmente

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))
andrea_crotti
fuente
55
recuerdeimport types
nguyên
13
types.ClassTypeya no es necesario en Python 3 (y se elimina).
kawing-chiu
esto no funciona con las nuevas clases de estilo en absoluto ... incluso en Python 2. No use esta solución solo
Erik Aronesty
Eso fue tomado del módulo de inspección, así que dudo que no funcione. Es simple verificar con Python2.7 por ejemploIn [8]: class NewStyle(object): ...: pass ...: In [9]: isinstance(NewStyle, (type, types.ClassType)) Out[9]: True
andrea_crotti
Esta es la implementación de Python 2, que tiene que manejar clases de estilo antiguo y nuevo. Python 3 simplifica esto a isinstance(object, type). Tenga en cuenta que los objetos como int, list, str, etc, son también las clases, por lo que no puede usar esto para distinguir entre clases personalizadas definidas en Python y incorporados en las clases definidas en el código C .
Martijn Pieters
39
>>> class X(object):
...     pass
... 
>>> type(X)
<type 'type'>
>>> isinstance(X,type)
True
S.Lott
fuente
1
Hm ... Buena respuesta, pero cuando escribo (Foo) en mi clase de Foo, dice <type 'classobj'> en lugar de <type 'type'>. Supongo que la diferencia proviene del hecho de que X hereda del objeto, pero Foo no. ¿Hay alguna otra diferencia que surja de esto? Gracias.
jeeyoungk
66
No funciona para las clases de estilo antiguo: 'class Old:pass' 'isinstance(Old, type) == False'pero inspect.isclass(Old) == True.
jfs
1
@jeeyoungk: No estás "asumiendo que la diferencia proviene de ...", en realidad estás leyendo eso en el código. Una subclase de objeto ("nuevo estilo") tiene las propiedades deseadas, justo lo que ve aquí.
S.Lott
12
Aquí está la pista: dado que esto funciona para clases de estilo nuevo, no use clases de estilo antiguo. No tiene sentido usar clases de estilo antiguo.
S.Lott
isinstance (e, f) E es el objeto instanciado, F es el objeto de clase.
Dexter
24
isinstance(X, type)

Regrese Truesi Xes clase y Falsesi no.

qnub
fuente
3
Me sale falso, incluso si X es una clase.
Mads Skjern
66
Esto solo funciona para nuevas clases de estilo. Las clases de estilo antiguo son del tipo 'classobj'. Entonces, si está utilizando clases de estilo antiguas, puede hacer: importar tipos isinstance (X, types.ClassType)
Charles L.
2
Esto parece ser lo mismo que S. Lott's answer, que es cuatro años mayor.
Ethan Furman
5

Esta comprobación es compatible con Python 2.xy Python 3.x.

import six
isinstance(obj, six.class_types)

Esta es básicamente una función de contenedor que realiza la misma verificación que en la respuesta andrea_crotti.

Ejemplo:

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

La forma más sencilla es utilizarlo inspect.isclasstal como aparece en la respuesta más votada.
los detalles de implementación se pueden encontrar en python2 inspect y python3 inspect .
para la clase de estilo nuevo: isinstance(object, type)
para la clase de estilo antiguo: isinstance(object, types.ClassType)
em, para la clase de estilo antiguo, está utilizando types.ClassType, aquí está el código de types.py :

class _C:
    def _m(self): pass
ClassType = type(_C)
lyu.l
fuente
1

Benjamin Peterson tiene razón sobre el uso de inspect.isclass()este trabajo. Pero tenga en cuenta que puede probar si un Classobjeto es específico Classy, por lo tanto, implícitamente Class, utilizando la función incorporada issubclass . Dependiendo de su caso de uso, esto puede ser más pitónico.

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

Entonces se puede usar así:

>>> class X():
...     pass
... 
>>> isclass(X)
True
>>> isclass(X())
False
masi
fuente
-2

Ya hay algunas soluciones de trabajo aquí, pero aquí hay otra:

>>> import types
>>> class Dummy: pass
>>> type(Dummy) is types.ClassType
True
Ztyx
fuente
types.ClassTypefue eliminado en Python 3
Beau Barker