如何检查一个变量是否为类对象

21

假设有一个简单的类:

class MyClass(object):
    pass

.
.
.
m = MyClass
print type(m) # gets: <type 'classobj'>
# if m is classobj, how can i check a variable is class object?

我的问题是:如何检查一个变量是否为类对象?

一个简单的解决方案:

if str(type(m)) == "<type 'classobj'>":
    # do something

但我认为至少有一种经典的方法可以检查。


1
上面展示的代码不会为type(m)打印<type 'classobj'>,因为 m 是新式类。它将打印 <type 'type'>。而经典类才会得到 <type 'classobj'> - abarnert
5个回答

42

使用inspect函数:

import inspect
print inspect.isclass(obj)

+1 用于检查模块 - pylover
现在我为什么没想到那个...(+1) - mgilson
我不知道我怎么会忘记这个,但这是一个比我的答案(以及与我的相当)更好的答案。 - abarnert
1
@abarnert -- 是的,但你的解释了所有的工作原理,这绝对值得保留。 - mgilson
你的所有答案都是最好的答案。但是为了更好的解释,abarnert的答案被接受了。 - pylover
显示剩余2条评论

26
在2.x中,类对象可以是type(新式类)或classobj(旧式类)。type类型是一个内置类型,但classobj类型不是。那么,你如何获取它?这就是types模块的作用。
isinstance(MyClass, (types.TypeType, types.ClassType))

在3.x版本中,你不需要担心经典类(classic classes),所以:

isinstance(MyClass, type)

即使您想直接比较类型,也不应该通过它们的str来比较任何对象。比较:

>>> class MyClassicClass:
...     pass
>>> str(type(MyClassicClass)) == "<type 'classobj'>"
True
>>> str("<type 'classobj'>") == "<type 'classobj'>"
True

通常可以直接比较对象:

>>> type(MyClassicClass) == types.ClassType
True
>>> "<type 'classobj'>" == types.ClassType
False

在极少数需要比较字符串表示的情况下,您需要使用repr而不是str


1
这是一个非常好的答案。+1(如果可以的话,我会给更多) - mgilson
我喜欢Jochen的答案因为它很简单,但这是一个好的解释。 - Nitzle
six库具有预定义的值,可涵盖Python 2或3。请参见class_types - Russell B
似乎types.ClassType在Python 3.10中已经不存在了。 - Sasha O

8
一个新式类(如你的示例中明确从object派生,或在Python 3中隐式派生)不是classobj类型。只有旧式类是classobj。因此,对于你编写的示例类,你可以简单地检查MyClass是否是type的实例,因为所有新式类都是如此。
isinstance(MyClass, type)

因为所有新式类都继承自object,所以您也可以这样做:
issubclass(MyClass, object)

我建议不要:

type(MyClass) == type

如果一个类的类型不是type,而是元类,则此方法将失效。当然,也可能存在这种情况。

如果您确实需要确定是否有旧式类,请导入types模块并使用types.ClassType,或者只需声明一个旧式类并查看您正在测试的类是否属于相同类型:

class OldStyleClass:
   pass
OldStyleClass = type(OldStyleClass)

isinstance(MyClass, OldStyleClass)

3

这是您要找的内容吗?

>>> class A(object):
...    pass
>>> isinstance(A, type)
True

>>> isinstance("asd", type)
False

但仅适用于从object继承的类。


我非常确定这不是 OP 寻找的内容。 - mgilson

0
有时候下一个(如果你想确定如何打印对象)是有效的。
def is_class(o):
    return hasattr(o, '__dict__')

大多数对象,包括类,都具有这个属性。 - pylover
@pylover 对不起,我回答了另一个问题:“如何确定变量是否为类实例”。我同意你的观点。但是你能否举个例子,说明哪些对象不是类并具有此属性? - sergzach
不,问题是如何检查一个变量是否为OBJECT类,而不是实例。 - pylover
你的方法对于类或实例总是返回 true。 - pylover
@pylover i = int(5) 是一个对象,因为issubclass(int, object)True,但是对于整数来说该方法返回False,因为int不是真正的用户定义类。所以,它不是真正类的实例。 - sergzach
你没有理解好问题。 - pylover

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