关于python:如何检查(在运行时)一个类是否是另一个类的子类?

How do I check (at runtime) if one class is a subclass of another?

假设我有一套西装和四个子套装:心形、铁锹形、钻石形、梅花形。

1
2
3
4
5
6
7
8
9
10
class Suit:
   ...
class Heart(Suit):
   ...
class Spade(Suit):
   ...
class Diamond(Suit):
   ...
class Club(Suit):
   ...

我有一个方法,它接收一个suit作为参数,它是类对象,而不是实例。更准确地说,它可能只接受四种价值观中的一种:心、铲、钻石、俱乐部。我怎样才能做出一个保证这样一件事的断言呢?类似:

1
2
3
def my_method(suit):
   assert(suit subclass of Suit)
   ...

我使用的是python 3。


你可以像这样使用issubclass()


issubclass(class, classinfo)

Excerpt:

Return true if class is a subclass (direct, indirect or virtual) of
classinfo.


如果有实例,可以使用isinstance;如果有类,可以使用issubclass。通常认为这是个坏主意。通常在Python中,通过尝试对某个对象执行该操作,可以确定该对象是否能够执行某个操作。


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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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。但是类型检查通常被认为是不必要的,因为您可以使用duck类型。


最小可运行示例

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/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中测试。


1
2
3
4
5
6
7
8
9
10
#issubclass(child,parent)

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

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