328

I was wondering how to check whether a variable is a class (not an instance!) or not.

I've tried to use the function isinstance(object, class_or_type_or_tuple) to do this, but I don't know what type a class would have.

For example, in the following code

class Foo:
    pass

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

I tried to substitute "class" with ???, but I realized that class is a keyword in python.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
jeeyoungk
  • 3,315
  • 2
  • 18
  • 6
  • In Python 3, the `???` equals to `type`. See also: [inspect.isclass](https://github.com/python/cpython/blob/7f01f77f8fabcfd7ddb5d99f12d6fc99af9af384/Lib/inspect.py#L191) implementation. – Niko Föhr Apr 27 '23 at 05:58

14 Answers14

477

Even better: use the inspect.isclass function.

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

>>> x = X()
>>> isinstance(x, X)
True
>>> inspect.isclass(x)
False
Richard de Wit
  • 7,102
  • 7
  • 44
  • 54
Benjamin Peterson
  • 19,297
  • 6
  • 32
  • 39
  • 15
    If you also want `inspect.isclass` to return `True` if the object to inspect is a *class instance*, use `inspect.isclass(type(Myclass()))` – michaelmeyer Apr 18 '13 at 16:21
  • 14
    @michaelmeyer `type(whatever)` always returns an object that is a class, so this check is redundant. If it didn't there would be no way to instantiate `whatever` and thus you couldn't perform the check in the first place. – a_guest Dec 16 '16 at 12:42
  • 1
    Doesn't work for me. Using python3 with snakemake, `type(snakemake.utils)` returns `` and yet `inspect.isclass(snakemake.utils)` returns `False`. – tedtoal Jul 03 '18 at 16:09
  • 6
    That's because `snakemake.util` is a module not a class? – Benjamin Peterson Aug 26 '18 at 19:41
  • 1
    @tedtoal `type(snakemake.utils)` returning `` means `snakemake.utils` is an _object_ of class _module_. So `isclass()` behavior is correct. – pepoluan Nov 08 '20 at 04:48
  • 3
    As of this writing, in the [`inspect.py`](https://github.com/python/cpython/blob/7f01f77f8fabcfd7ddb5d99f12d6fc99af9af384/Lib/inspect.py#L191) module of the python standard library, the `isclass(object)` function is a one-liner: `return isinstance(object, type)`. – Jasha Jun 18 '21 at 09:27
  • 1
    It's true that `inspect.isclass` was more useful in Python 2, where there were old and new-style classes to worry about. Perhaps the one remaining advantage of that function is that the intent is very clear. – Benjamin Peterson Jul 23 '21 at 17:41
63
>>> class X(object):
...     pass
... 
>>> type(X)
<type 'type'>
>>> isinstance(X,type)
True
S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • 1
    Hm... Nice answer, but when i do type(Foo) on my Foo class, it says instead of . I assume that the diference comes from the fact that X is inheriting from the object, but Foo isn't. Is there any other difference arising from this? Thanks. – jeeyoungk Dec 28 '08 at 03:24
  • 7
    It doesn't work for old-style classes: `'class Old:pass' 'isinstance(Old, type) == False'`, but `inspect.isclass(Old) == True`. – jfs Dec 28 '08 at 08:03
  • 2
    @jeeyoungk: You're not "assuming the difference comes from...", you're actually reading that in the code. A subclass of object ("new style") has the desired properties, just what you see here. – S.Lott Dec 28 '08 at 12:27
  • 17
    Here's the hint -- since this works for new-style classes, don't use old-style classes. There's no point to using old-style classes. – S.Lott Dec 28 '08 at 14:15
  • 1
    isinstance(e, f) E is the instantiated object, F is the class object. – Dexter Apr 28 '15 at 19:30
  • 1
    This won't work if your class X has a metaclass. If it has a metaclass, then the metaclass will be returned rather than type. – spacether Nov 04 '21 at 18:48
  • 4
    By the way, all classes are new-style in Python 3 - there is no classobj, so this is better than importing inspect just to check if variable is class. – Adam Jenča May 17 '22 at 17:02
52

The inspect.isclass is probably the best solution, and it's really easy to see how it's actually implemented

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

    Class objects provide these attributes:
        __doc__         documentation string
        __module__      name of module in which this class was defined"""
    return isinstance(obj, (type, types.ClassType))
Xiao
  • 12,235
  • 2
  • 29
  • 36
andrea_crotti
  • 3,004
  • 2
  • 28
  • 33
  • 7
    remember `import types` – nguyên May 16 '14 at 01:27
  • 19
    `types.ClassType` is no longer needed in Python 3 (and is removed). – kawing-chiu Mar 08 '16 at 01:35
  • 3
    this doesn't work with new style classes at all.... even in python 2. dont use this solution alone – Erik Aronesty Apr 19 '17 at 18:51
  • That was taken from the inspect module so I doubt it doesn't work. It's simple to check with Python2.7 for example `In [8]: class NewStyle(object): ...: pass ...: In [9]: isinstance(NewStyle, (type, types.ClassType)) Out[9]: True` – andrea_crotti Apr 27 '17 at 12:30
  • 5
    This is the Python 2 implementation, which has to handle old-style and new-style classes. Python 3 simplifies this to `isinstance(object, type)`. Note that objects like `int`, `list`, `str`, etc. are **also** classes, so you can't use this to distinguish between *custom classes defined in Python* and *built-in classes defined in C code*. – Martijn Pieters Jan 06 '18 at 14:27
  • 4
    Don't call your argument `object`. That shadows the prominent built-in name `object`. – Reinderien Jun 04 '20 at 14:48
  • interesting to have so many upvotes for something that is so incorrect now, regardless of how well it worked before: **this DOESNT WORK on Python 3**. – JL Peyret Apr 05 '21 at 19:21
  • @JLPeyret The code shown - demonstrating an implementation of `inspect.isclass` - doesn't work, but `inspect.isclass` still does. The implementation changed. – Karl Knechtel Jul 27 '22 at 21:50
44
isinstance(X, type)

Return True if X is class and False if not.

qnub
  • 677
  • 5
  • 6
  • 4
    I get False, even if X is a class. – Mads Skjern Jun 12 '12 at 11:12
  • 8
    This only works for new style classes. Old style classes are of type 'classobj'. So if you're using old style classes you can do: import types isinstance(X, types.ClassType) – Charles L. Jul 11 '13 at 20:22
  • 5
    This appears to be the same as [`S. Lott's answer`](https://stackoverflow.com/a/395741/208880), which is four years older. – Ethan Furman Oct 10 '17 at 06:50
  • This should be the accepted answer for Python 3, as all classes are "new style" classes there. See also [inspect.isclass](https://github.com/python/cpython/blob/7f01f77f8fabcfd7ddb5d99f12d6fc99af9af384/Lib/inspect.py#L191) implementation, which is exactly this. One line. No need to import anything. – Niko Föhr Apr 27 '23 at 05:54
7

This check is compatible with both Python 2.x and Python 3.x.

import six
isinstance(obj, six.class_types)

This is basically a wrapper function that performs the same check as in andrea_crotti answer.

Example:

>>> import datetime
>>> isinstance(datetime.date, six.class_types)
>>> True
>>> isinstance(datetime.date.min, six.class_types)
>>> False
Sergey
  • 627
  • 1
  • 9
  • 16
4

Benjamin Peterson is correct about the use of inspect.isclass() for this job. But note that you can test if a Class object is a specific Class, and therefore implicitly a Class, using the built-in function issubclass. Depending on your use-case this can be more pythonic.

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

Can then be used like this:

>>> class X():
...     pass
... 
>>> isclass(X)
True
>>> isclass(X())
False
omni
  • 4,104
  • 8
  • 48
  • 67
  • This `Type[Any]` seems wrong: if the function were indeed expecting a `Type[Any]` it wouldn’t need the `try`/`except`. – bfontaine Jan 06 '23 at 18:34
1

class Foo: is called old style class and class X(object): is called new style class.

Check this What is the difference between old style and new style classes in Python? . New style is recommended. Read about "unifying types and classes"

Community
  • 1
  • 1
JV.
  • 2,658
  • 4
  • 24
  • 36
  • 8
    This should have been a comment perhaps? – Kos Nov 28 '12 at 12:18
  • In addition to this maybe should have been a comment, the information is outdated. In Python 3, while `class Foo(object): ...` is equivalent to `class Foo: ...` this [answer on why one would inherit from object](https://stackoverflow.com/a/45062077/2364215) – hlongmore Nov 03 '22 at 18:08
1

simplest way is to use inspect.isclass as posted in the most-voted answer.
the implementation details could be found at python2 inspect and python3 inspect.
for new-style class: isinstance(object, type)
for old-style class: isinstance(object, types.ClassType)
em, for old-style class, it is using types.ClassType, here is the code from types.py:

class _C:
    def _m(self): pass
ClassType = type(_C)
lyu.l
  • 282
  • 3
  • 8
1

The simplest solution I found and use successfully is:

 def isclass(cls):
    return str(type(cls)).startswith("<class") and hasattr(cls, '__weakref__')
Anthony M.
  • 98
  • 5
0

Well, inspect.isclass is not working for me, instead, try this

class foo:
    pass

var = foo()

if str(type(var)).split(".")[0] == "<class '__main__":
    print("this is a class")
else:
    print(str(type(var)).split(".")[0])

So basically, type(var) is <class 'a type'>

Example: <class 'int' But, when var is a class, it will appear something like <class '__main__.classname'>

So we split the string into <class '__main__ and we compare using if, if the string fit perfectly then it's a class

enter image description here

Kirro Smith
  • 71
  • 1
  • 3
0

If you are using a class decorator, inspect.isclass() will not work since the class is wrapped by a function. Instead, use inspect.unwrap() first, then test with inspect.isclass().

Example:

import functools
import inspect

def class_decorator(cls):
    @functools.wraps(cls)
    def wrapper(*args, **kwargs):
        return cls(*args, **kwargs)
    return wrapper

@class_decorator
class Spam:
    pass

print(inspect.isclass(Spam)) # False
print(type(Spam)) # class 'function'

print(inspect.isclass(inspect.unwrap(Spam))) # True
print(inspect.unwrap(Spam)) # class 'Spam'
Ryan H.
  • 2,543
  • 1
  • 15
  • 24
-1

There is an alternative way to check it:

import inspect

class cls():
     print(None)

inspect.isclass(cls)

Reference: https://www.kite.com/python/docs/inspect.isclass

Md. Jamal Uddin
  • 754
  • 8
  • 17
-1

In some cases (depending on your system), a simple test is to see if your variable has a __module__ attribute.

if getattr(my_variable,'__module__', None):
    print(my_variable, ".__module__ is ",my_variable.__module__)
else:
    print(my_variable,' has no __module__.')

int, float, dict, list, str etc do not have __module__

Ben Law
  • 58
  • 6
-2

There are some working solutions here already, but here's another one:

>>> import types
>>> class Dummy: pass
>>> type(Dummy) is types.ClassType
True
Ztyx
  • 14,100
  • 15
  • 78
  • 114