如何检查一个变量是否是一个类?

332
我想知道如何检查一个变量是不是类(而不是实例!)。
我尝试使用函数isinstance(object,class_or_type_or_tuple)来做到这一点,但我不知道类会有什么类型。
例如,在以下代码中:
class Foo:
    pass

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

我试图用???替换"class",但我意识到class是Python中的关键字。


在Python 3中,???等于type。参见:inspect.isclass 实现。 - Niko Pasanen
14个回答

480

更好的方法是使用 inspect.isclass函数。

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

>>> x = X()
>>> isinstance(x, X)
True
>>> inspect.isclass(x)
False

16
如果您希望inspect.isclass在检查的对象是类实例时也返回True,请使用inspect.isclass(type(Myclass())) - michaelmeyer
14
type(whatever)始终返回一个类的对象,因此这个检查是多余的。如果不是这样,就无法实例化whatever,因此您根本无法进行检查。 - a_guest
7
这是因为snakemake.util是一个模块而不是一个类? - Benjamin Peterson
5
截至本文撰写时,在Python标准库的inspect.py模块中,isclass(object)函数是一行代码:return isinstance(object, type) - Jasha
2
“inspect.isclass”在Python 2中更有用,因为需要考虑旧式类和新式类。也许这个函数仅剩下的优点是其意图非常明确。 - Benjamin Peterson
显示剩余2条评论

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

7
对于旧式类来说这不起作用:'class Old:pass' 'isinstance(Old, type) == False',但是inspect.isclass(Old) == True - jfs
2
@jeeyoungk:你并不是“假设差异来自于...”,而是在代码中实际读取到了。对象的子类(“新样式”)具有所需的属性,就像你在这里看到的一样。 - S.Lott
18
提示是,由于这适用于新式类,请勿使用旧式类。使用旧式类没有任何意义。 - S.Lott
2
如果你的类X有一个元类,这段代码将无法工作。如果它有一个元类,那么返回的将是元类而不是type。 - spacether
6
顺便说一下,在Python 3中,所有的类都是新式类 - 没有classobj,因此这比导入inspect模块来检查变量是否为类要更好。 - Adam Jenča
显示剩余2条评论

53

inspect.isclass可能是最好的解决方案,而且很容易看出它实际上是如何实现的。

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))

7
记住 import types - nguyên
19
types.ClassType 在 Python 3 中不再需要(已被移除)。 - kawing-chiu
3
这根本不适用于新风格类...即使在Python 2中也是如此。不要单独使用此解决方案。 - Erik Aronesty
5
这是Python 2的实现,必须处理旧式和新式类。Python 3将其简化为isinstance(object, type)。请注意,像 intliststr等对象也是类,因此您不能使用它来区分在Python中定义的自定义类和在C代码中定义的内置类。 - Martijn Pieters
4
不要将你的参数命名为 object。这会掩盖 Python 中重要的内置名称 object - Reinderien
显示剩余3条评论

45
isinstance(X, type)

如果X是类,则返回True,否则返回False


4
即使X是一个类,我还是得到False。 - Mads Skjern
8
这只适用于新式类。旧式类的类型为 “classobj”。因此,如果您正在使用旧式类,可以执行以下操作:import types isinstance(X, types.ClassType) - Charles L.
9
这似乎与S. Lott的回答相同,而该回答比此回答早四年。 - Ethan Furman
1
这应该是Python 3的被接受答案,因为所有类都是“新式”类。请参见inspect.isclass实现,就是这样。一行代码,无需导入任何内容。 - Niko Pasanen

7

这个检查适用于Python 2.x和Python 3.x。

import six
isinstance(obj, six.class_types)

这基本上是一个包装函数,执行与andrea_crotti答案中相同的检查。

示例:

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

4

关于这个工作,Benjamin Peterson正确地使用了inspect.isclass()。 但请注意,您可以使用内置函数issubclass测试一个Class对象是否是特定的Class,因此隐含地是一个Class。 根据您的用例,这可能更具有Pythonic风格。

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

然后可以像这样使用:

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

这个 Type[Any] 看起来不对:如果函数确实期望一个 Type[Any],那么它就不需要 try/except - bfontaine

1

8
这或许应该作为一条评论? - Kos
除了这个可能应该是一个注释,这个信息已经过时了。在Python 3中,虽然class Foo(object): ...等同于class Foo: ...,但是为什么要从object继承的答案已经更新。 - hlongmore

1
我找到并成功使用的最简单的解决方案是:
 def isclass(cls):
    return str(type(cls)).startswith("<class") and hasattr(cls, '__weakref__')

你的方法可能不适用于所有情况:__weakref__ 属性会自动添加到继承自 object 并且没有显式设置 __slots__(不包括 __weakref__)的用户定义类的实例中。这个属性允许对象被弱引用,意味着你可以创建对该对象的弱引用而不增加其引用计数。 - undefined

1

最简单的方法是使用最多投票答案中发布的inspect.isclass
实现细节可以在python2 inspectpython3 inspect中找到。
对于新式类:isinstance(object, type)
对于旧式类:isinstance(object, types.ClassType)
嗯,对于旧式类,它使用types.ClassType,这是来自types.py的代码:

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

0
好的,inspect.isclass对我不起作用,相反,请尝试这个。
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])

基本上,type(var)<class 'a type'>

例如:<class 'int'。但是,当 var 是一个类时,它会出现类似于 <class '__main__.classname'> 的东西。

所以我们将字符串分成<class '__main__,并使用if进行比较,如果字符串完全符合,则是一个类。

enter image description here


2
我不认为我得到了任何投票哈哈 - Kirro Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接