isinstance() 和 issubclass() 返回冲突结果

34 投票
4 回答
28535 浏览
提问于 2025-04-17 06:11

你怎么解释 isinstance(Hello,object) 返回 True,而 issubclass(Hello,object) 返回 False 呢?

>>> class Hello:
    pass

还有

>>> isinstance(Hello,object)
True
>>> issubclass(Hello,object)
False
>>> a = Hello()
>>> isinstance(a,object)
True

4 个回答

19

我的回答是关于Python 3的。

为了进一步解释cbare的回答,下面的代码对我很有帮助。

>>> class X:
...     pass
...     
>>> class Y(X):
...     pass
...     
>>> x = X()
>>> y = Y()
>>> isinstance(x, X)  # is object x an instance of class X (or any subclass)?
True
>>> isinstance(x, Y)  # is object x an instance of class Y (or any subclass)?
False
>>> isinstance(y, X)  # is object y an instance of class X (or any subclass)?
True
>>> isinstance(y, Y)  # is object y an instance of class Y (or any subclass)?
True

>>> issubclass(X, X)  # is class X a subclass of X (including class X)?
True
>>> issubclass(X, Y)  # is class X a subclass of Y (including class Y)?
False
>>> issubclass(Y, X)  # is class Y a subclass of X (including class X)?
True
>>> issubclass(Y, Y)  # is class Y a subclass of Y (including class Y)?
True

>>> issubclass(type(x), X)  # is class of object x a subclass of X (including class X)?
True
>>> issubclass(type(x), Y)  # is class of object x a subclass of Y (including class Y)?
False
>>> issubclass(type(y), X)  # is class of object y a subclass of X (including class X)?
True
>>> issubclass(type(y), Y)  # is class of object y a subclass of Y (including class Y)?
True

>>> issubclass(x.__class__, X)  # is class of object x a subclass of X (including class X)?
True
>>> issubclass(x.__class__, Y)  # is class of object x a subclass of Y (including class Y)?
False
>>> issubclass(y.__class__, X)  # is class of object y a subclass of X (including class X)?
True
>>> issubclass(y.__class__, Y)  # is class of object y a subclass of Y (including class Y)?
True

我们可以看到,isinstance(object, class)能够正确处理继承和子类的关系。

101

这个被接受的答案是对的,但似乎漏掉了一个重要的点。内置的函数 isinstanceissubclass 其实是在问两个不同的问题。

isinstance(对象, 类信息) 是在问一个 对象 是否是某个 的实例(或者是多个类的组合)。

issubclass(类, 类信息) 是在问一个 是否是另一个类(或者多个类)的子类。

在这两种方法中,类信息 可以是“类、类型,或者多个类、类型的组合”。

因为类本身也是对象,所以使用 isinstance 是完全可以的。我们也可以问一个类是否是另一个类的子类。不过,我们不应该期待这两个问题会得到相同的答案。

class Foo(object):
    pass

class Bar(Foo):
    pass

issubclass(Bar, Foo)
#>True
isinstance(Bar, Foo)
#>False

Bar 是 Foo 的子类,而不是它的实例。Bar 是 type 的一个实例,而 typeobject 的子类,因此类 Bar 是 object 的一个实例。

isinstance(Bar, type)
#>True
issubclass(type, object)
#>True
isinstance(Bar, object)
#>True
27

这是因为你在使用旧式类,所以它没有从 object 这个基础类派生。你可以试试这个:

class Hello(object):
    pass

>>> issubclass(Hello,object)
True

旧式类已经不推荐使用了,你不应该再用它们。

在 Python 3.x 中,所有的类都是新式类,写 (object) 已经不再需要了。

撰写回答