我如何检查(在运行时)如果一个类是另一个的子类?

假设我有一个类Suit和四个子类Suit:红心、黑桃、方块、梅花。

class Suit:
...
class Heart(Suit):
...
class Spade(Suit):
...
class Diamond(Suit):
...
class Club(Suit):
...

我有一个方法,它接收suit作为参数,这是一个类对象,而不是一个实例。更准确地说,它可能只接受四个值中的一个:红心,黑桃,方块,梅花。我怎么能做出保证这样的断言呢?喜欢的东西:

def my_method(suit):
assert(suit subclass of Suit)
...

我用的是Python 3。

141437 次浏览

issubclass(class, classinfo)

摘录:

的子类(直接、间接或虚)则返回true classinfo . < / p >

你可以像这样使用issubclass()

如果你有一个实例,你可以使用isinstance;如果你有一个类,你可以使用issubclass。通常认为这是个坏主意。通常在Python中,你通过尝试对一个对象做某件事来判断它是否有能力做某件事。

你可以使用内置的is子类。但是类型检查通常被认为是不必要的,因为您可以使用duck-typing。

如果给定的子类sub确实是父类sup的子类,issubclass(sub, sup)布尔函数返回true。

使用is子类似乎是一种编写日志级别的干净方法。用它感觉有点奇怪……但它似乎比其他选择更干净。

class Error(object): pass
class Warn(Error): pass
class Info(Warn): pass
class Debug(Info): pass


class Logger():
LEVEL = Info


@staticmethod
def log(text,level):
if issubclass(Logger.LEVEL,level):
print(text)
@staticmethod
def debug(text):
Logger.log(text,Debug)
@staticmethod
def info(text):
Logger.log(text,Info)
@staticmethod
def warn(text):
Logger.log(text,Warn)
@staticmethod
def error(text):
Logger.log(text,Error)
#issubclass(child,parent)


class a:
pass
class b(a):
pass
class c(b):
pass


print(issubclass(c,b))#it returns true

issubclass最小可运行示例

下面是一个包含一些断言的更完整的例子:

#!/usr/bin/env python3


class Base:
pass


class Derived(Base):
pass


base = Base()
derived = Derived()


# Basic usage.
assert issubclass(Derived, Base)
assert not issubclass(Base, Derived)


# True for same object.
assert issubclass(Base, Base)


# Cannot use object of class.
try:
issubclass(derived, Base)
except TypeError:
pass
else:
assert False


# Do this instead.
assert isinstance(derived, Base)

GitHub上游

在Python 3.5.2中测试。

根据Python文档,我们还可以使用class.__mro__属性或class.mro()方法:

class Suit:
pass
class Heart(Suit):
pass
class Spade(Suit):
pass
class Diamond(Suit):
pass
class Club(Suit):
pass


>>> Heart.mro()
[<class '__main__.Heart'>, <class '__main__.Suit'>, <class 'object'>]
>>> Heart.__mro__
(<class '__main__.Heart'>, <class '__main__.Suit'>, <class 'object'>)


Suit in Heart.mro()  # True
object in Heart.__mro__  # True
Spade in Heart.mro()  # False