读到《Fluent Python》的 Chapter 11 “Interfaces: From Protocols to ABCs”,里面讲到的接口,协议和抽象基类都不难理解,读到 “Virtual Subclass” 虚拟子类有点乱了。
举的例子(这几节的例子都太抽象了,读得我难受)大概长这样:
后面给的测试结果是这样:
我们可以看到由于 TomboList 要继承 list,所以不能做抽象基类 Tombola 的子类,但是为了 issubclass 和 isinstance 的判断处理,做了一个注册 @Tombola.register 。
我们知道继承抽象基类必须要重载所有的抽象方法之后才能实例化,但当我自己测试的时候发现,这里的注册 register 是不判断方法的,所以这里注册之后也不是真正的子类,那么上面说到的 issubclass 和 isinstance 是怎么判断的呢?
查!我找到了这个回答提到的这篇博文里的这个引用,里面讲到,重写下面两个魔术方法可以改变 issubclass 和 isinstance 的行为。
所以 register 大概就是通过改变抽象基类的这两个方法里的一些参数,从而实现注册的效果,补个链接,顺便提一嘴在抽象基类实现类方法 __subclasshook__ 也能达到注册的效果,还不用一个一个的 register。
收工!