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

sna*_*ile 176 python assert subclass

假设我有一套西装和四个西装子类:Heart,Spade,Diamond,Club.

class Suit:
   ...
class Heart(Suit):
   ...
class Spade(Suit):
   ...
class Diamond(Suit):
   ...
class Club(Suit):
   ...
Run Code Online (Sandbox Code Playgroud)

我有一个接收套装作为参数的方法,它是一个类对象,而不是一个实例.更确切地说,它可能只收到四个值中的一个:Heart,Spade,Diamond,Club.我怎样才能做出确保这样的事情的断言?就像是:

def my_method(suit):
   assert(suit subclass of Suit)
   ...
Run Code Online (Sandbox Code Playgroud)

我正在使用Python 3.

小智 200

你可以issubclass()像这样使用assert issubclass(suit, Suit).

  • 如果在Stack Overflow上有一件事是常数,那么任何带有暗示isinstance或issubclass的答案的问题也会伴随着有关鸭子打字的讲座! (134认同)
  • "但你为什么要做这样的事呢?" - 因为你有一个容器类,你需要确保它是同质的,唯一的方法是在插入时检查类型? (54认同)
  • 子类测试使得很多东西的单元测试,特别是Django的模型,更加容易."Python不是Java." 为什么python程序员必须拥有这样的芯片? (28认同)
  • 我遇到了这个问题,试图弄清楚如何检测我的numpy dtype是否为图像处理应用程序的float或int.如果它是一个浮点数,则惯例是在0.0和1.0之间进行标准化,如果它是int则则约定为0到255.我可以通过各种扭曲来尝试使图像变得嘎嘎,但它更直接到只要问"你是一只鸭子"并相应地扩展我的操作. (25认同)
  • 没有贬低,纯粹是因为最后缺乏想象力和相当傲慢的言论.解释为什么一个人可能不需要这样做会更友好,更有帮助. (20认同)
  • 关于你为什么要这样做的原因.对于命令行程序,我使用issubclass对模块的属性构建简单的命令行接口"my_program.py <有效子类列表调用>",所以如果我收集了my_module.Foo(Command),你可以调用`my_program Foo`它会通过内省调用`Foo.Run()` (5认同)
  • 要记住的一件事:`一个类被认为是它自己的子类.https://docs.python.org/2/library/functions.html#issubclass (3认同)
  • 鸭子打字不会删除用例.以Django的信号框架为例.send_robust返回(接收器,响应)的元组,其中响应可能是接收者的返回值,或者它可能是异常子类.使用issubclass()来确定哪个是完全有效的用例. (3认同)
  • 此外..我根本没有发现“鸭子打字”更优雅。1行检查是否为鸭子,而3行尝试/捕获异常处理。我将采用1行解决方案..谢谢! (3认同)
  • 是的。每个套装都是一个类,是套装的一个子类。我在这里想要的是四个可能的值。没有 Suit 的实例,也没有 Heart、Spade、Club 或 Diamond 的实例。他们是单身狗。这是一个糟糕的设计吗? (2认同)
  • @AlexT python的“鸭子输入”原理背后的思想是,如果一个对象的行为类似于其他对象,则应这样对待它,并在尝试对其进行操作之前,请先不检查其是否为正确的类。例如,如果您的函数需要一个列表,但是它所做的只是对列表中的元素进行迭代,那么它应该只进行迭代而不必断言该变量包含一个列表。这样,使用您的函数的人就可以传入一个元组或一个类似于列表的对象,并且它仍然可以正常工作,而不必不必要地破坏。 (2认同)
  • 另一方面,@AlexT Java对此要严格得多,您必须确保该变量在尝试迭代它之前支持迭代。 (2认同)
  • 不是试图自由地抨击你的答案,但因为它是公认的......你的例子几乎意味着一个人会使用`issubclass(instance, Class)`,而它实际上是`issubclass(Class, Superclass)` (2认同)

Kat*_*iel 44

issubclass(class, classinfo)

摘抄:

如果class是子类(直接,间接或虚拟), 则返回true classinfo.


Dav*_*nan 26

isinstance如果您有实例,或者issubclass您有课程,则可以使用.通常认为这是个坏主意.通常在Python中,如果一个对象能够通过尝试对其执行某些操作来解决问题,则可以解决问题.

  • @Michael Scheper:我不得不说,如果这是pythonic方式,那么我真的很讨厌pythonic方式.IMO,不应将例外用于控制流程.如果您认为可能发生错误,请防止它...不要将其视为GOTO.但是,您发布了有趣的链接 (6认同)
  • @wrongusername:这是'Pythonic'的方式,是的.我认为这个习惯有优点,所以只要它保持我的代码清晰,我就会遵循它.这里有一个很好的讨论:http://stackoverflow.com/questions/7604636/better-to-try-something-and-catch-the-exception-or-test-if-its-possible-first (2认同)

Jam*_*ani 20

issubclass(sub, sup)如果给定的子类布尔函数返回真sub不愧是超类的子类sup.

  • 答案没有误导演讲+1. (8认同)

Cir*_*四事件 13

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)
Run Code Online (Sandbox Code Playgroud)

GitHub 上游.

在 Python 3.5.2 中测试。


YaO*_*OzI 7

根据Python doc,我们还可以使用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
Run Code Online (Sandbox Code Playgroud)