具体化抽象基类的两种方式:
1、通过抽象基类 ABCMeta 的 register 方法注册。
2、通过继承的方式。
class Base(metaclass = ABCMeta):
@classmethod
def __subclasshook__(cls, subclass):
if cls is Base:
return True
return NotImplemented
class Derive(Base):
pass
print(issubclass(int, Base)) #True
print(issubclass(int, Derive)) #False
issubclass 放回会调用 __subclasscheck__,isinstance 会调用 __instancecheck__.
issubclass(int, Base) 调用 Base.__subclasscheck__(int) 方法。Base.__subclasscheck__ 方法来自 ABCMate 元类。
调用 ABCMate 的 __subclasscheck__ 方法,ABCMate 的 __subclasscheck__ 返回会调用 __subclasshook__ 方法。
def __subclasscheck__(cls, subclass):
"""Override for issubclass(subclass, cls)."""
# Check cache
if subclass in cls._abc_cache:
return True
# Check negative cache; may have to invalidate
if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
# Invalidate the negative cache
cls._abc_negative_cache = WeakSet()
cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
elif subclass in cls._abc_negative_cache:
return False
# Check the subclass hook
ok = cls.__subclasshook__(subclass) #check 方法调用 hook
if ok is not NotImplemented:
assert isinstance(ok, bool)
if ok:
cls._abc_cache.add(subclass)
else:
cls._abc_negative_cache.add(subclass)
return ok
if cls is Base: 确保了只有 Base 类自己调用该方法时,走这一分支;如果是 Base 类的派生类调用,则走下一分支,返回 NotImplemented 走默认实现。
__subclasscheck__ 检查一个类是否是另外一个类的子类,所以只能用在元类上。
issubclass(MySubCls, MyCls)
#等价于 MyCls.__subclasscheck(MySubCls)
抽象基类的用处:
1、继承自抽象基类,必须实现抽象基类的所有 abstractmethod ,这样在对象创建阶段就会检查,而不用等到调用方法时。
2、将 ducktype 的检测(是否拥有某方法)统一到 issubclass 和 isinstance 上。
如果正确的实现了接口,便是子类,而不用通过继承的方式。
hasattr(x, '__iter__') 替换成 isinstance(x, collections.Iterable)