前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python的抽象基类

python的抽象基类

作者头像
哒呵呵
发布2018-08-06 15:22:28
8560
发布2018-08-06 15:22:28
举报
文章被收录于专栏:鸿的学习笔记鸿的学习笔记

与jvm上的语言不一样,python的语言没有interface关键字,而且除了抽象基类,每个类都有相应的接口:类实现或继承的公开属性(方法或数据类型)

在定义里,受保护的属性和私有属性不在接口中:即便“受保护的”属性也只是采用名称改写,私有属性也是可以轻松访问。

公开数据属性是可以变成特性,可以转换成只读,例如:

class test():

    def __init__(self,x):
        self.__x = x
    @property    
    def x(self):
        return self.__x
a = test(3)
a.x
Out[3]: 3

接口是实现特定方法的集合,协议和继承没有关系,一个类可能实现多个接口,从而让实例扮演多个角色。

接下来再继续看看序列协议。我们定义一个类:

class test1():

    def __getitem__(self,pos):
        return range(3)[pos]
a = test1()
a[1]
Out[13]: 1
2 in a
Out[14]: True
for i in a:
    print(i)
0
1
2

在这个类,我们只是实现了__getitem__,python自动就帮你实现了迭代,contains方法。

协议的动态本性:

python里面有个方法shuffle,可以就地打乱序列,如下:

from random import shuffle
l = list(range(3))
shuffle(l)
l
Out[23]: [1,2,0]

但是我们应用在上面那个例子:

class test1():

    def __init__(self):
        self.alist = list(range(20))
    def __getitem__(self,pos):
        print(pos)
        return self.alist[pos]
    def __len__(self):
        return len(range(20))
a = test1()
shuffle(a)
Traceback (most recent call last):
  File "<ipython-input-49-ef6bc136c33f>",line 1,in <module>
    shuffle(a)
  File "D:\Users\chuancy\AppData\Local\Continuum\Anaconda3\lib\random.py",line 272,in shuffle
    x[i],x[j] = x[j],x[i]
TypeError: 'test1' object does not support item assignment

我们可以发现shuffle函数需要调换集合中元素的位置,而test1实现的是不可变序列,可变序列还需要实现__setitem__方法

def setitem(self,key,value):
    self.alist[key] = value
test1.__setitem__ = setitem
shuffle(a)
9
19
10

setitem的参数的名只是约定一样,只不过python会往里面传参数,类的方法本质上也只是一个函数而已。

我们可以在test1已经实例化后,再设置__setitem__,在运行时修改类和模块,而不改动源码,这就是所谓的“猴子补丁”。

“鸭子类型”:忽略对象的真正类型,转而关注对象有没有实现所需的方法,签名和语义。

继承抽象基类很简单,只要实现python里的特殊方法__len__之类的,这样python就会自动识别。

抽象基类的继承大多都是在collections模块,现在打开这个模块的文档看看。

ABC Inherits from Abstract Methods Mixin Methods

Container __contains__(支持in)

Hashable __hash__

Iterable __iter__(支持可迭代)

Iterator Iterable next __iter__

Sized __len__(支持len)

Callable __call__

Sequence Sized,Iterable,Container __getitem__,__len__ __contains__,__iter__,__reversed__,index,and count

MutableSequence Sequence __getitem__,__setitem__,__delitem__,__len__,insert Inherited Sequence methods and append,reverse,extend,pop,remove,and __iadd__

Set Sized,Iterable,Container __contains__,__iter__,__len__ __le__,__lt__,__eq__,__ne__,__gt__,__ge__,__and__,__or__,__sub__,__xor__,and isdisjoint

MutableSet Set __contains__,__iter__,__len__,add,discard Inherited Set methods and clear,pop,remove,__ior__,__iand__,__ixor__,and __isub__

Mapping Sized,Iterable,Container __getitem__,__iter__,__len__ __contains__,keys,items,values,get,__eq__,and __ne__

MutableMapping Mapping __getitem__,__setitem__,__delitem__,__iter__,__len__ Inherited Mapping methods and pop,popitem,clear,update,and setdefault

MappingView Sized __len__

ItemsView MappingView,Set __contains__,__iter__

KeysView MappingView,Set __contains__,__iter__

ValuesView MappingView __contains__,__iter__

从官方文档中可以看出,一共有16个基类,分为三层:

--顶层是Iterable,Container,Sized,Callable,Hashable:

其中Iterable,Container,Sized是各个集合该继承的三个抽象基类,或者至少实现兼容的协议。

Callable,Hashable只要是为isinstance提供支持,并且计算hash值

--再往下是Sequence,Mapping,Set,MappingView,Iterator

Sequence,Mapping,Set是不可变类型,都有自己可变的子类

MappingView是散列表的映射,.items(),.keys(),.values()返回的对象的是ItemView,KeysView,ValuesView

在_collections_abc.py中

class Hashable(metaclass=ABCMeta):
    __slots__ = ()
    @abstractmethod
    def __hash__(self):
        return 0
    @classmethod
    def __subclasshook__(cls, C):
        if cls is Hashable:
            for B in C.__mro__:
                if "__hash__" in B.__dict__:
                    if B.__dict__["__hash__"]:
                        return True
                    break
        return NotImplemented

取出一个来看__subclasshook__这个方法,这个是用于检查继承的类是否确实是Hashable的子类,也就是判断是否存在__hash__

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-08-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档