python中的隐式继承
先看一个例子
from typing import Sized
class MyLen:
def __len__(self):
return 10
print(issubclass(MyLen, Sized))
print(MyLen.__mro__)
输出为True,但是我们没有显示继承Sized类,打印__mro__,同样没有Sized类。这是因为在python中可以通过实现一些协议、方法来隐式继承类型。
如果实现了__getitem__魔法方法,自定义对象就能称为”序列类型”,可以使用类似list序列那样的操作。python还定义了基础类型的协议,例如:
Hashable = _alias(collections.abc.Hashable, 0) # Not generic.
Awaitable = _alias(collections.abc.Awaitable, 1)
Coroutine = _alias(collections.abc.Coroutine, 3)
AsyncIterable = _alias(collections.abc.AsyncIterable, 1)
AsyncIterator = _alias(collections.abc.AsyncIterator, 1)
只要实现了指定魔法方法,无需显示继承,也可以让我们的类是Awaitable的。
我们可以自定义一套类型体系来实现隐式继承。这需要metaclass与__subclasshook__等技术的辅助。
class MyBase(metaclass=ABCMeta):
@classmethod
def __subclasshook__(cls, C):
if cls is MyBase:
if any("my_method" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
class ImplementsMethod:
def my_method(self):
pass
class DoesNotImplementMethod:
pass
print(issubclass(ImplementsMethod, MyBase)) # 输出: True
print(issubclass(DoesNotImplementMethod, MyBase)) # 输出: False
现在只要有一个类拥有my_method方法,就可以通过issubclass方法的判断,相当于可以自定义协议。
此外还有两个魔法方法__subclasscheck__与__instancecheck__,用来判断是否是一个类的子类或是实例。
class Test(metaclass=ABCMeta):
@classmethod
def __subclasscheck__(cls, subclass):
print("__subclasscheck__", cls, subclass)
if 'my_method' in subclass.__dict__:
return True
return False
print(issubclass(ImplementsMethod, Test))
输出依然为False,并且Test的类的__subclasscheck__方法并没有被调用。这两个方法需要被定义在元类中才可以生效。
class MyMeta(type):
def __instancecheck__(cls, instance):
print("__instancecheck__", cls, instance)
return True
def __subclasscheck__(cls, subclass):
print("__subclasscheck__", cls, subclass)
if 'my_method' in subclass.__dict__:
return True
return False
class Test(metaclass=MyMeta):
pass
print(issubclass(ImplementsMethod,
Test)) # True __subclasscheck__ <class '__main__.Test'> <class '__main__.ImplementsMethod'>
print(isinstance(ImplementsMethod, Test)) # True
浙公网安备 33010602011771号