python中的抽象被称为 duck typing模式,如果它看起来像一只鸭子并且叫起来像一只鸭子,那么它大概就是一只鸭子。
有很多种方式实现抽象,特点也不同

  1. 使用NotImplementedError,这种也是最基础使用最多的方式
    NotImplemented return一个没有实现的标记,表示可以由其他对象实现
    NotImplementError raise一个没有实现的错误,必须实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    class A:
    def __init__(self, v):
    self.v = v

    def __eq__(self, other):
    print('A eq')
    if isinstance(other, A):
    return self.v == other.v
    if isinstance(other, B):
    return other.v == self.v
    if isinstance(other,C):
    return False
    return NotImplemented


    class B:
    def __init__(self, v):
    self.v = v

    def __eq__(self, other):
    print('B eq')
    if isinstance(other, B):
    return self.v == other.v
    return NotImplemented

    class C:
    def __eq__(self, other):
    raise NotImplementedError

    a = A(1)
    b = B(3)
    c = C()
    print(a == b)
    print('-'*20)
    print(b == a)
    print('-'*20)
    print(a == c)
    print('-'*20)
    print(b == c)
    ### 输出为
    A eq
    False
    --------------------
    B eq
    A eq
    False
    --------------------
    A eq
    False
    --------------------
    B eq
    Traceback (most recent call last):
    File "/Users/didi/code/python/test/pack.py", line 45, in <module>
    print(b == c)
    File "/Users/didi/code/python/test/pack.py", line 34, in __eq__
    raise NotImplementedError
    NotImplementedError

可以看出来

  1. a==b 调用的过程是A::__eq__,因为A::__eq__里实现了与B的比较,
  2. b==a调用过程是B::__eq__->A::__eq__,因为B::__eq__中没有实现与A的比较,所以返回了一个NotImplemented,这样会去调用A::__eq__,所以得到了False
  3. a == c b == c与上面类似,不过因为C::__eq__直接抛出了一个NotImplementedError所以程序直接报错了
  1. 元类 见 python-抽象-metaclass