Python中自定义的类只要实现了某种特殊的协议,就能赋予那种行为,举一个简单的例子:python
class A: def __len__(self): return 0 a = A() print(len(a))
如上所示,本身定义了一个类,实现了__len__的魔法方法,就能够使用内置函数len()获取对象长度。若是实现了__getitem__魔法方法,自定义对象就能称为”序列类型”,能够使用相似list序列那样的操做,好比a[1]获取第2个元素......ssh
在Java中,有interface接口的概念,而在Python中没有这个概念,取而代之的是抽象基类。在Python中定义一个抽象基类以下:函数
import abc class Base(abc.ABC): @abc.abstractmethod def func(self): """doc"""
只须要实现func的接口便可code
class MyClass(Base): def func(self): pass
Python原生定义了抽象基类Sized,里面实现了__len__方法,咱们能够自定义类来继承Sized,实现里面的__len__方法,Sized源码以下:对象
class Sized(metaclass=ABCMeta): __slots__ = () @abstractmethod def __len__(self): return 0 @classmethod def __subclasshook__(cls, C): if cls is Sized: return _check_methods(C, "__len__") return NotImplemented
如上所示,咱们看到了它实现了__subclasshook__方法,检查子类和子类的mro上全部的类是否有__len__方法,若是没有,返回NotImplemented。固然咱们没必要继承Sized,而是使用虚拟子类(virtual subclass)技术,只实现__len__协议,隐式继承了Sized。继承
下面咱们仿造Sized自定义一个抽象基类
接口
import abc class Base(abc.ABC): @abc.abstractmethod def my_protocol(self): """自定义协议""" @classmethod def __subclasshook__(cls, subclass): if cls is Base: if any("my_protocol" in B.__dict__ for B in subclass.__mro__): return True return NotImplemented
接下来咱们定义一个子类,隐式继承Base
get
#并无显式继承Base class MyClass: def my_protocol(self): pass if __name__ == '__main__': k = MyClass() print(isinstance(k, Base)) #True print(issubclass(MyClass, Base)) #True print(Base._abc_impl)
如上所示,咱们只须要实现my_protocol
协议,就会隐式继承自抽象基类,这样就实现了虚拟子类的建立源码