Python 抽象基类的理解

Python 抽象基类的理解

一、抽象基类的特点:

1.规定继承类必须具有抽象基类指定的方法

2.抽象基类无法实例化

以上两个特点,主要用于接口设计

注意:Python中并没有提供抽象类与抽象方法,但是提供了内置模块abc来模拟实现抽象类

二、使用场景:

1.判断某个对象的类型:

class ColorObj(object):
    """创建一个颜色的类"""

    def __init__(self, color_list):
        """初始化方法"""
        self.color = color_list

    def __len__(self):
        return len(self.color)


color = ColorObj(['red', 'yellow', 'blue'])

from collections.abc import Sized
result = isinstance(color, Sized)
print(result)

# 输出结果: True
  • isinstance 用来判断一个对象的实例,Color都没有继承Sized,可是为什么会返回True,这些就可以想到鸭子类型(是动态类型的一种风格),下面看一下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
    

    解释:这个Sized的抽象基类,它会继承metaclass=ABCMeta, 并且@abstractmethod 抽象方法,关键判断它是否有__ len __ 方法在于下面的 __ subclasshook __ 魔法方法。

2.强制子类必须实现某些方法:

  • 首先看一下,上面所说的特点抽象基类无法实例化:

    import abc
    
    class BaseObj(metaclass=abc.ABCMeta):
        """基类"""
    
        @abc.abstractmethod  # 给该方法添加装饰器
        def get(self, value):
            print(value)
    
        @abc.abstractmethod
        def set(self, key, value):
            print(key, value)
    
    
    base_obj = BaseObj()  # 实例化BaseObj的时候报错
    print(base_obj)
    
    # 报错信息:
    Traceback (most recent call last):
      File "C:/Users/lh9/PycharmProjects/request/Python魔法函数.py", line 121, in <module>
        base_obj = BaseObj()
    TypeError: Can't instantiate abstract class BaseObj with abstract methods get, set
    
  • 强制子类实现的方法:

    class BaseObj(metaclass=abc.ABCMeta):
        """基类"""
    
        @abc.abstractmethod
        def get(self, value):
            print(value)
    
        @abc.abstractmethod
        def set(self, key, value):
            print(key, value)
    
    
    class Dog(BaseObj):
    
        def get(self, value):
            print(value)
    
    
    dog = Dog()
    print(dog.get('fe_cow'))
    
    # 输出结果会报错:
    Traceback (most recent call last):
      File "C:/Users/lh9/PycharmProjects/request/Python魔法函数.py", line 127, in <module>
        dog = Dog()
    TypeError: Can't instantiate abstract class Dog with abstract methods set
    

    报错原因:因为我们继承的BaseObj类中,get、set方法都添加了装饰器@abc.abstractmethod,说明要继承BaseObj的子类,必须要实现get、set方法,否则会报错。

    class BaseObj(metaclass=abc.ABCMeta):
        """基类"""
    
        @abc.abstractmethod
        def get(self, value):
            print(value)
    
        @abc.abstractmethod
        def set(self, key, value):
            print(key, value)
    
    
    class Dog(BaseObj):
    
        def get(self, value):
            print(value)
            return value
    
        def set(self, key, value):
            pass
    
    dog = Dog()
    print(dog.get('fe_cow'))
    
    # 输出结果:
    fe_cow
    fe_cow
    

三、collection.abc模块常用的抽象基类:

__all__ = ["Awaitable", "Coroutine",
           "AsyncIterable", "AsyncIterator", "AsyncGenerator",
           "Hashable", "Iterable", "Iterator", "Generator", "Reversible",
           "Sized", "Container", "Callable", "Collection",
           "Set", "MutableSet",
           "Mapping", "MutableMapping",
           "MappingView", "KeysView", "ItemsView", "ValuesView",
           "Sequence", "MutableSequence",
           "ByteString",
           ]

感兴趣的可以看看这些源码

你可能感兴趣的:(Python)