使用Python内置的issubclass方法很方便的检测一个类是否是另一个类的子类。
这个是issubclass的文档:
issubclass(class, classinfo)
Return true if class is a subclass (direct, indirect or virtual) of classinfo. A class is considered a subclass of itself. classinfo may be a tuple of class objects, in which case every entry in classinfo will be checked. In any other case, a TypeError exception is raised.
一个类的子类可以是直接的、间接的、或者是虚拟的。
issubclass的第二个参数classinfo可以是一个类对象或者包含类对象的tuple(只要其中一个检测成功即返回True)。
一些使用示例:
> class A(object): ... pass ... > class B(A): ... pass ... > class C(B, A): ... pass ... > class D(C): ... pass ... > issubclass(D, D), issubclass(D, C), issubclass(D, B), issubclass(D, A), issubclass(D, object) (True, True, True, True, True) > D.__bases__ (<class '__main__.C'>,) > D.__mro__ (<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
D是D的子类,D定义时的基类是C,所以D是C的子类,而且D是B,A,object的间接子类。
__mro__是类属性, 在类定义完毕Python解析器便通过一种C3算法将所有的父类以method resolution order的顺序保存到一个元组里, 成为类的属性。
所以issubclass可以这样简单的实现:
def issubclass(cls, classinfo): if classinfo in cls.__mro__: return True return False
Python的issubclass是内置函数(一般是C实现),实际上要复杂很多,要检测参数类型,如第一个参数必须是type类型,第二个参数是type类型或者tuple类型。还要考虑该类是否是虚拟的子类,以及子类的子类。
例如:
> from collections import abc > class E: ... def __len__(self): ... return 1 ... > issubclass(E, abc.Sized) True > E.__mro__ (<class '__main__.E'>, <class 'object'>) > class F: ... pass ... > issubclass(F, abc.Sized) False > abc.Sized.register(F) <class '__main__.F'> > issubclass(F, abc.Sized) True
Python是动态类型语言,长久以来使用Duck type(鸭子类型)形式编程,不管对象是什么类型,只要实现了所需要的方法。
现在有了ABCs, 可以用于判断某个类或者某个对象是不是ABCs的子类或者实例,但这个类并不需要显示的继承于ABCs, 因为python内置的ABCs有一种注册机制可将一个类注册为它的子类。如上例子的register方法。
还有一种机制是可以定制一个__subclasshook__方法,将某种类型的类认定为子类。
如abc.Sized的__subclasshook__是这样子的:
@classmethod def __subclasshook__(cls, C): if cls is Sized: if any("__len__" in B.__dict__ for B in C.__mro__): return True return NotImplemented
所以有__len__方法的E类是abc.Sized的子类, 这个__subclasshook__方法是通过__subclasscheck__方法调用的,这个__subclasscheck__是每一个ABC类都有的方法,在ABCMeta类(其他ABC类都继承于它)实现。
现在的issubclass函数的实现,会先判断classinfo是否有__subclasscheck__方法,如果有此方法,则判断子类的逻辑由该方法返回,即覆盖issubclass的实现(CPython)。
__subclasscheck__会分几个步骤进行判断:
- 调用__subclasshook__方法,如果有方法定义
- 检查自己是否在待检测类的__mro__列表里
- 递归检查待检测类是否是在注册子类(内置_abc_registry列表属性)
- 递归检查待检测类是否是自己子类的子类
具体源码在: https://github.com/python/cpython/blob/3.6/Lib/abc.py#L194-L231
相关的CPython实现在: https://github.com/python/cpython/blob/0ccc0f6c7495be9043300e22d8f38e6d65e8884f/Objects/abstract.c#L2223
而基本上isinstance(object, classinfo)方法的实现只需要调用issubclass(type(object), classinfo)
参考:
29.7. abc — Abstract Base Classes : https://docs.python.org/3/library/abc.html
PEP 3119 – Introducing Abstract Base Classes: https://www.python.org/dev/peps/pep-3119/
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- [发烧人声]群星《邂逅》DTS-WAV
- 艻打绿《夏/狂热(苏打绿版)》[320K/MP3][106.42MB]
- 艻打绿《夏/狂热(苏打绿版)》[FLAC分轨][574.2MB]
- 黄雨勳《魔法列车首部曲》[320K/MP3][33.1MB]
- 李蕙敏.2014-记得·销魂新歌+精丫乐意唱片】【WAV+CUE】
- 谢金燕.1995-含泪跳恰蔷冠登】【WAV+CUE】
- 于文文.2024-天蝎座【华纳】【FLAC分轨】
- 黄雨勳《魔法列车首部曲》[FLAC/分轨][173.61MB]
- 群星《歌手2024 第13期》[320K/MP3][50.09MB]
- 群星《歌手2024 第13期》[FLAC/分轨][325.93MB]
- 阿木乃《爱情买卖》DTS-ES【NRG镜像】
- 江蕾《爱是这样甜》DTS-WAV
- VA-Hair(OriginalBroadwayCastRecording)(1968)(PBTHAL24-96FLAC)
- 博主分享《美末2RE》PS5 Pro运行画面 玩家仍不买账
- 《双城之战2》超多新歌MV发布:林肯公园再次献声