温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

使用Python实现issubclass的方法

发布时间:2021-02-03 13:37:30 来源:亿速云 阅读:197 作者:小新 栏目:开发技术

小编给大家分享一下使用Python实现issubclass的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

使用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__会分几个步骤进行判断:

  1. 调用__subclasshook__方法,如果有方法定义

  2. 检查自己是否在待检测类的__mro__列表里

  3. 递归检查待检测类是否是在注册子类(内置_abc_registry列表属性)

  4. 递归检查待检测类是否是自己子类的子类

具体源码在: 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)

以上是“使用Python实现issubclass的方法”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI