python 抽象基类

具体化抽象基类的两种方式:

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)

猜你喜欢

转载自blog.csdn.net/zhouguoqionghai/article/details/82660192
今日推荐