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。
- 至于suit是一个诉讼子类的实例,还是一个类对象,这个问题还不清楚。下面的答案涵盖了两种可能性。
- @利奥波德:真的不清楚吗?我已经明确地说明了my_method可以得到的四个可能值作为参数:"它可能只收到四个值中的一个:心、铲、钻石、俱乐部"。这些值是类对象,而不是类实例。我觉得这很清楚,不过我想你说得对,因为答案确实涵盖了两种可能性。如果你有更清晰的措辞,欢迎你编辑这个问题。谢谢你的评论。
- @是的,还不清楚。由于依赖于任何人的自我表达的正确性,在这个话题上都是小菜一碟。很多新来者不能得到的东西都是一个对象,在python的东西中,可以表达一个东西,但可以思考另一个。这是一个现实,除了纯洁,从新来者那里期望这种行为是很合理的。留下你的名誉点是你在这里的表达是否正确的唯一直接暗示,还是我应该说,"就正确性而言"。我理解把你的知识考虑进去的愿望,而且不考虑不断更新的新来者仍然是不合理的。
- @因此,我们可以合理地使用命名约定,将这些参数名后加上_class,使它们与suit_class相似。我在一个相关问题中提出了这样一个命名约定。
- 建议在示例代码中添加四行my_method(Heart)my_method(Spade)…
你可以像这样使用issubclass()。
- 你已经把我的答案从IsInstance改为IsubClass。你真的在传递类而不是对象?
- 对。每件西装都是一个等级,是西装的一个子类。我想要的是四个可能的值。没有西服的例子,也没有心形、铁锹、梅花或钻石的例子。他们是单身汉。那是个坏设计吗?
- "但你为什么要做这种事?"--因为您有一个容器类,您需要确保它是同构的,唯一的方法是在插入时检查类型?
- 我有一个测试来确保我的处理程序是basehandler的子类,并且它们不是字符串。(以后可能会懒散地进口)
- 如果有一件事是堆栈溢出时的常量,那就是任何带有答案的问题(意味着isInstance或issubClass)也将伴随有关duck类型的讲座!
- 关于你为什么要做那部分。对于命令行程序,我对模块的属性使用issubclass来构建简单的命令行接口"my program.py
",因此如果我收集了我的module.foo(command),您可以调用my_program Foo,它将通过内省调用Foo.Run()。
- 我遇到这个问题,试图找出如何检测我的numpy数据类型是浮点型还是图像处理应用程序的int型。如果它是一个浮点,那么约定是在0.0和1.0之间进行规范化,如果它是int,那么约定是0到255。我可以通过各种各样的扭曲来尝试让图像抖动,但更直接的方法是问"你是鸭子吗"并相应地缩放我的操作。
- 请记住:A class is considered a subclass of itself.docs.python.org/2/library/functions.html issubclass
- duck类型不能删除这个用例。以Django的信号框架为例。send-robust返回(receiver,response)的元组,其中response可能是receiver的返回值,也可能是异常子类。使用issubclass()确定哪一个用例是完全有效的。
- 子类测试使许多东西的单元测试变得更容易,特别是Django的模型。"Python不是Java。"为什么Python程序员必须有这样的芯片在他们的肩膀上?
- 不赞成,纯粹是因为最后的话缺乏想像力,相当傲慢。解释一个人为什么不需要这样做会更友好和更有帮助。
- 对于大多数用例来说,猜测isInstance已经足够了。
- if issubclass(type(e), Exception): logger.exception(...) else: logger.error(...)
- 有人能解释一下"Python不是Java"的意思吗?不明白这是什么意思:(
- @Alext,python的"duck-typing"哲学背后的思想是,如果一个对象的行为与其他对象类似,那么你应该这样对待它,而不是在试图对它进行操作之前检查它是否是正确的类。例如,如果函数需要一个列表,但它所做的只是对列表中的元素进行迭代,那么它应该只进行迭代,而不断言变量包含列表。这样,使用函数的人可以传递一个元组或一个类似于列表的对象,它仍然可以工作,而不是不必要地中断。
- 另一方面,@ AlxEdJava更严格,并且必须确保变量在迭代之前要支持迭代。
- 不是想随便抨击你的答案,但既然它是公认的答案…你的例子几乎暗示了一个人会使用issubclass(instance, Class),而实际上它是issubclass(Class, Superclass)。
- 此外…我觉得"鸭子打字"一点也不优雅。一行检查看它是否是一个鸭子,而三行尝试/捕获异常处理。我要一线解决方案……谢谢!
issubclass(class, classinfo)
Excerpt:
Return true if class is a subclass (direct, indirect or virtual) of
classinfo.
如果有实例,可以使用isinstance;如果有类,可以使用issubclass。通常认为这是个坏主意。通常在Python中,通过尝试对某个对象执行该操作,可以确定该对象是否能够执行某个操作。
- 如果你发现你不能用它做那件事怎么办?你发现一个异常并尝试其他方法吗?
- @错误的用户名:这是"Python"的方式,是的。我认为这个习惯有优点,所以我遵循它,只要它保持我的代码清晰。这里有一个很好的讨论:stackoverflow.com/questions/7604636/…
- @迈克尔:我不得不说,如果这是Python的方式,那么我真的讨厌Python的方式。IMO,例外情况不应用于控制流。如果您认为可能发生错误,请保护它…不要把它当作一个Goto。不过,你发布的链接很有趣
- @在你00以上:听起来像是你所说的那种违反"只要它能让我的代码保持清晰"。不过,我不喜欢所有的Python习俗,因为很多人滥用EAFP原则,最终导致很难找到虫子。
如果给定的子类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 |
- 只写代码的答案是不受欢迎的,因此,您应该总是在代码中添加一些解释性文字。然而,这个答案是多余的:它没有添加在前面的答案中没有提到的信息。