Como verificar se uma variável é uma classe ou não?

236

Eu queria saber como verificar se uma variável é uma classe (não uma instância!) Ou não.

Eu tentei usar a função isinstance(object, class_or_type_or_tuple)para fazer isso, mas não sei que tipo uma classe terá.

Por exemplo, no código a seguir

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

Eu tentei substituir " class" por ??? , mas percebi que classé uma palavra-chave em python.

jeeyoungk
fonte

Respostas:

335

Melhor ainda: use a inspect.isclassfunção

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

>>> x = X()
>>> isinstance(x, X)
True
>>> y = 25
>>> isinstance(y, X)
False
Benjamin Peterson
fonte
7
Se você também quiser inspect.isclassa devolução Truese o objeto para inspecionar é uma instância de classe , o usoinspect.isclass(type(Myclass()))
michaelmeyer
8
Melhor do que o que :)?
Mad Physicist
8
@michaelmeyer type(whatever)sempre retorna um objeto que é uma classe, portanto essa verificação é redundante. Caso contrário, não haveria maneira de instanciar whatevere, portanto, você não poderia executar a verificação em primeiro lugar.
a_guest
Não funciona para mim. Usando python3 com snakemake, type(snakemake.utils)retorna <class 'module'>e ainda inspect.isclass(snakemake.utils)retorna False.
tedtoal
3
Isso porque snakemake.utilum módulo não é uma classe?
Benjamin Peterson
44

A inspect.isclass é provavelmente a melhor solução e é realmente fácil ver como ela é realmente implementada

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
fonte
5
lembre-seimport types
nguyên
13
types.ClassTypenão é mais necessário no Python 3 (e é removido).
Kawing-chiu 8/03/16
Isso não funciona com as novas classes de estilo em tudo .... mesmo em python 2. uso não faça esta solução por si só
Erik Aronesty
Isso foi retirado do módulo de inspeção, então duvido que não funcione. É simples verificar com o Python2.7, por exemploIn [8]: class NewStyle(object): ...: pass ...: In [9]: isinstance(NewStyle, (type, types.ClassType)) Out[9]: True
andrea_crotti
Esta é a implementação do Python 2, que precisa lidar com classes de estilo antigo e novo. O Python 3 simplifica isso para isinstance(object, type). Note-se que objetos como int, list, str, etc, são também as classes, para que você não pode usar isso para distinguir entre classes personalizadas definidas em Python e built-in classes definidas no código C .
Martijn Pieters
39
>>> class X(object):
...     pass
... 
>>> type(X)
<type 'type'>
>>> isinstance(X,type)
True
S.Lott
fonte
1
Hum ... Boa resposta, mas quando eu digito (Foo) na minha classe Foo, ele diz <type 'classobj'> em vez de <type 'type'>. Suponho que a diferença vem do fato de que X é herdado do objeto, mas Foo não. Existe alguma outra diferença decorrente disso? Obrigado.
jeeyoungk
6
Não funciona para aulas de estilo antigo:, 'class Old:pass' 'isinstance(Old, type) == False'mas inspect.isclass(Old) == True.
JFS
1
@jeeyoungk: Você não está "assumindo que a diferença vem de ...", na verdade está lendo isso no código. Uma subclasse de objeto ("novo estilo") tem as propriedades desejadas, exatamente o que você vê aqui.
315/08 S.Lott
12
Aqui está a dica - como isso funciona para classes de novo estilo, não use classes de estilo antigo. Não faz sentido usar classes de estilo antigo.
315/08 S.Lott
isinstance (e, f) E é o objeto instanciado, F é o objeto de classe.
Dexter
24
isinstance(X, type)

Retorne Truese Xfor classe e Falsese não for.

qnub
fonte
3
Fico falso, mesmo que X seja uma classe.
Mads Skjern
6
Isso funciona apenas para novas classes de estilo. As classes de estilo antigo são do tipo 'classobj'. Então, se você estiver usando as classes de estilo antigo que você pode fazer: tipos de importação isinstance (X, types.ClassType)
Charles L.
2
Parece ser o mesmo que S. Lott's answer, quatro anos mais velho.
Ethan Furman 10/10
5

Essa verificação é compatível com o Python 2.xe o Python 3.x.

import six
isinstance(obj, six.class_types)

Essa é basicamente uma função de wrapper que executa a mesma verificação que na resposta andrea_crotti.

Exemplo:

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

A maneira mais simples é usar inspect.isclasscomo postado na resposta mais votada.
os detalhes da implementação podem ser encontrados em python2 inspecionar e python3 inspecionar .
para classe de estilo novo: isinstance(object, type)
para classe de estilo antigo: isinstance(object, types.ClassType)
em, para classe de estilo antigo, está usando types.ClassType, aqui está o código de types.py :

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

Benjamin Peterson está correto sobre o uso de inspect.isclass()para este trabalho. Mas observe que você pode testar se um Classobjeto é um específico Classe, portanto, implicitamente a Class, usando a função interna issubclass . Dependendo do seu caso de uso, isso pode ser mais pitônico.

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

Pode então ser usado assim:

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

Já existem algumas soluções de trabalho aqui, mas aqui está outra:

>>> import types
>>> class Dummy: pass
>>> type(Dummy) is types.ClassType
True
Ztyx
fonte
types.ClassTypefoi removido em Python 3
Beau Barker