How to check whether a variable is a class or not?
Asked Answered
M

14

336

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.

Mckale answered 28/12, 2008 at 3:8 Comment(1)
In Python 3, the ??? equals to type. See also: inspect.isclass implementation.Tetherball
B
491

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
Bonesetter answered 28/12, 2008 at 3:47 Comment(7)
If you also want inspect.isclass to return True if the object to inspect is a class instance, use inspect.isclass(type(Myclass()))Invalid
@Invalid 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.Jointress
Doesn't work for me. Using python3 with snakemake, type(snakemake.utils) returns <class 'module'> and yet inspect.isclass(snakemake.utils) returns False.Palindrome
That's because snakemake.util is a module not a class?Bonesetter
@Palindrome type(snakemake.utils) returning <class 'module'> means snakemake.utils is an object of class module. So isclass() behavior is correct.Spiritualize
As of this writing, in the inspect.py module of the python standard library, the isclass(object) function is a one-liner: return isinstance(object, type).Zagreb
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.Bonesetter
E
71
>>> class X(object):
...     pass
... 
>>> type(X)
<type 'type'>
>>> isinstance(X,type)
True
Enhanced answered 28/12, 2008 at 3:11 Comment(7)
Hm... Nice answer, but when i do type(Foo) on my Foo class, it says <type 'classobj'> instead of <type 'type'>. 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.Mckale
It doesn't work for old-style classes: 'class Old:pass' 'isinstance(Old, type) == False', but inspect.isclass(Old) == True.Saree
@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.Enhanced
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.Enhanced
isinstance(e, f) E is the instantiated object, F is the class object.Shoshone
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.Earthiness
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.Chil
D
54

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))
Dichromaticism answered 12/4, 2012 at 12:24 Comment(8)
remember import typesDislimn
types.ClassType is no longer needed in Python 3 (and is removed).Eparchy
this doesn't work with new style classes at all.... even in python 2. dont use this solution aloneMaidinwaiting
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]: TrueDichromaticism
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.Ehling
Don't call your argument object. That shadows the prominent built-in name object.Bordello
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.Aeonian
@JLPeyret The code shown - demonstrating an implementation of inspect.isclass - doesn't work, but inspect.isclass still does. The implementation changed.Caput
R
45
isinstance(X, type)

Return True if X is class and False if not.

Reine answered 6/4, 2012 at 15:34 Comment(4)
I get False, even if X is a class.Sardonyx
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)Burushaski
This appears to be the same as S. Lott's answer, which is four years older.Majesty
This should be the accepted answer for Python 3, as all classes are "new style" classes there. See also inspect.isclass implementation, which is exactly this. One line. No need to import anything.Tetherball
S
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
Singularize answered 22/11, 2018 at 8:51 Comment(0)
B
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
Baro answered 4/4, 2020 at 11:57 Comment(1)
This Type[Any] seems wrong: if the function were indeed expecting a Type[Any] it wouldn’t need the try/except.Kail
M
2

The simplest solution I found and use successfully is:

 def isclass(cls):
    return str(type(cls)).startswith("<class") and hasattr(cls, '__weakref__')
Mona answered 5/6, 2023 at 1:58 Comment(1)
Your approach might not work in all cases: the __weakref__ attribute is automatically added to instances of user-defined classes that inherit from object and do not explicitly set __slots__ without including __weakref__. This attribute allows the object to be weakly referable, meaning you can create weak references to the object without increasing its reference count.Rodriques
T
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"

Thrombin answered 28/12, 2008 at 3:48 Comment(2)
This should have been a comment perhaps?Debunk
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 objectMedora
T
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)
Thallophyte answered 30/5, 2018 at 7:39 Comment(0)
M
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

Margertmargery answered 7/2, 2022 at 13:49 Comment(1)
I don't think i got any vote lolMargertmargery
V
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'
Vyse answered 3/4, 2023 at 0:11 Comment(0)
M
-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

Medin answered 13/6, 2021 at 16:20 Comment(1)
Why add a new answer about inspect.isclass? This duplicates Benjamin Peterson’s answer.Kail
D
-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__

Darnel answered 26/2, 2022 at 1:47 Comment(0)
R
-2

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

>>> import types
>>> class Dummy: pass
>>> type(Dummy) is types.ClassType
True
Reena answered 24/6, 2012 at 17:0 Comment(1)
types.ClassType was removed in Python 3Eaten

© 2022 - 2024 — McMap. All rights reserved.