python定义abc_Python中list与collections.abc.Sequence是什么关系?

首先list和Sequence的关系当然不是isinstance,而是应该用issubclass来判断。

但是,list的__mro__当中也的确没有Sequence,但却有issubclass(list, Sequence) == True

这是一个Python独有的OOP机制叫做subclass/subinstance hook,详细内容可以参见官方文档

简单来说,isinstance和issubclass两个内置函数有个hook挂载点,当需要判断的类型/父类的metaclass(注意,必须是metaclass上定义的,在class本身定义了这两个函数不生效)包含了__instancecheck__和/或者 __subclasscheck__两个magic函数的时候,会使用这两个定义的函数来做isinstance和issubclass的检测,从而覆盖默认的__mro__的机制。

从这个技术就诞生了标准库的abc库,它的主要目标是将一些传统上使用duck type检测(比如检查有没有特定的接口)的代码都统一到了isinstance和issubclass上,技术就是使用上面的两个方法。

那么对于Sequence来说,它使用abc中的metaclass,这个metaclass通过两种不同的技术来判断是否为subclass:应用__subclasshook__的方法,例如Iterable,任何定义了__iter__的类都会判断得到issubclass(MyClass, Iterable) == True

应用register,可以将其他类注册为该abc的子类,从而有issubclass(RegisteredClass, Sequence) == True

list就是通过register注册到了Sequence的一个子类MutableSequence上,从而成为Sequence的虚拟子类,即便它的__mro__中没有Sequence和MutableSequence。

题外话,这两种技术加上传统的__mro__判断在abc的实现中是交叉使用的,很有趣,比如说Iterable的判断,正常来说是通过有没有__iter__判断的,但是Iterable的直接子类(即继承于Iterable的类,包括其它abc)的机制也会产生影响,当前一个判断不为True的时候,会继续判断该类和Iterable的直接子类的关系。我们知道str其实是没有__iter__方法的,只有__getitem__,但Sequence是Iterable的子类,str又通过register机制成为了Sequence的子类,这样判断issubclass(str, Iterable)的时候,首先通过__subclasshook__判断失败,接着依次查找Iterable的子类,发现它是Sequence的子类,最终返回True,充分保证了子类的子类仍然是子类的OOP原则。list也是通过注册到MutableSequence而成为Sequence的子类的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值