[分享] Python的群集與ABC_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3047 | 回复: 0   主题: [分享] Python的群集與ABC        上一篇   下一篇 
fozhyn
注册用户
等级:上士
经验:317
发帖:101
精华:0
注册:2011-10-18
状态:离线
发送短消息息给fozhyn 加好友    发送短消息息给fozhyn 发消息
发表于: IP:您无权察看 2016-4-21 10:09:44 | [全部帖] [楼主帖] 楼主

想要认识一门语言,不单只是就语法部份,认识的设计与风格,也是极为重要的一部份。

 

在标准程序库为数众多的API中,从群集API的资料结构分类与阶层作为开始,是个不错的方式,对于Python这类将常用资料结构作为内建型态的语言,更是如此。

 

Python内建型态谈起

 

就语言来说,常用的资料结构,都会有一套标准实作。

 

有些语言将常用资料结构内建为语法的一部份,象是Pythonlistsettupledict等,都可使用实字方式撰写,这让程序变得简洁,也能应付大多数处理资料的需求;有些语言将这些实作以独立的API实作,象是JavaCollectionMap API等,让这类资料结构用来与程序语法泾渭分明,虽然语法囉嗦,然而,开发者较易(或说是强制要)掌握型态与实作品的特性。

 

对于熟悉Java的我而言,在使用Python语言,享用过这类资料结构作为直译器内建型态的好处之后,不免开始有了一些蒙胧的疑问,这些内建型态的实作特性呢?我很熟悉JavaCollectionMap API的设计架构,那么Pythonlistsettupledict的分类与阶层呢?

 

若不能掌握API设计架构,不但难以掌握各资料结构实作品的特性,也容易沦为死记API的窘境,更容易撰写出没有弹性的程序。

 

由于熟悉Java,一开始不免想要将Java中的界面与实作品,逐一在Python中找出对照物,不过,不久就发现方向似乎有点错误,毕竟两门语言的设计哲学不同,更何况是API的设计了,最大的差别之一是,Python是动态定型,而Java是静态定型语言,因此Python没有JavaCollectionMap那样的界面阶层,而是直接思考行为,将相关资料结构分为了SequencesSetMapping三种型态。

 

对于Sequence,它们都具有索引取值、切片等一些共同的行为,Python接着将Sequence进一步地区分了ImmutableMutable两种,strtuplebytes属于Immutable,而listbytearray属于Mutable,并具有Immutable几乎全部的行为,以及切片操作指定、appendremove等操作,然而,Immutable具备、但Mutable不一定会实作的行为是hash操作,因此Immutable的型态就可以作为dict的键,或者是setfrozenset的元素。

 

collections模块

 

所谓Sequence型态,并不是指它们真的有继承一个Sequence类别,而是指具备Sequence的行为,具体而言,就是像实作了lenindex这类的操作罢了,这让设计函式时更有弹性;进一步地,我开始想到setdict的行为,分别看来就象是Java中的HashSetHashMap,都是无序的,那么有没有TreeSetTreeMap呢?对于这类需求,Python提供了collections模块来满足。

 

collections模块中,可基于dict建立一个OrderedDict,它看来象是Java中的TreeMap,不过是以元素插入顺序来定序,这表示,若想在取得键值对时,能依自订顺序来取出,就必须先在一个Sequence中自行对键值排序,再用排序后的结果建立OrderedDict

 

JavaCollection架构中,有个Queue界面与子界面Deque,而在Python中,list本身可实现Queue甚至是Deque,不过要注意到效能问题——当从list前端取出或新增元素时,时间复杂度会是O(n),如果元素数量多的话,最好是改用collections模块中的deque,它的popleftappendleft时间复杂度会是O(1),当然,作为双向队列的实现,deque也提供了rotate之类的方法。

 

Python中,tuple的地位总是比较尴尬,很多层面它跟list类似,只不过它是Immutable,占用比较少的资源;然而,如果看过HaskellTuple,就会知道Tuple的元素型态,相当于临时组成了未命名的新型态,其实在Pythoncollections模块中,也有个类似的namedtuple函式,可让既有的tupleHaskell中的Tuple类似,充当临时的资料结构。例如:

 

Point = namedtuple('Point', ['x', 'y'])
p = Point(11, 22)
print(p.x + p.y)  # 
显示 
33


 

namedtuple是个工厂函式,传回的实际上是动态建立的tuple子类别,因此具有tuple的行为,然而具有指定的型态名称与栏位名称,也可以使用dot来存取栏位,这让它的实例就象是个Immutable物件,比一般物件节省资源,也可以充当dict来使用。

 

collections.abc模块

 

当然,collections中,还有象是Counter类别、defaultdict函式等可以使用,不过,终究还是没有发现象是JavaLinkedListTreeSet这类的东西。如果需要这类东西,必须要自行实作。例如,若需要list的全部功能,而且,在某些场合必须被判断为list实例(象是使用isinstance()判断,例如OrderedDict就是dict的子类别),那么可以继承list;如果只是要包裹一个list,并让包裹器行为上像个list,可以继承UserList

 

然而,如果只是要实作群集的行为,但不需要是群集中某个类别的子类别时,可以继承collections.abc模块中的相关类别——abc代表着abstract base classes,也就是这些类别是作为抽象基础类别,它们本身已经实作了一些行为。不过,还有些必要的抽象方法,必须开发者在继承之后自行定义,如果开发者忘了定义,建立实例时会引发TypeError,并告知忘了实作哪些抽象方法,这开发者免于记忆或查询有哪些方法必须实作。

 

而且,一旦开发者定义了必要的抽象方法,基于这些抽象方法的其他方法实作(Mixin Methods),就能够运作了,这会比完全自定义一个群集类别来得方便许多且不容易出错,比方说,在Pythoncollections.abc官方说明文件中,就有个〈OrderedSet recipe〉的文件链结,其中的OrderedSet,就是基于collections.MutableSet而实作。

 

collections.abc模块中,还有IterableIteratorHashable等抽象基础类别,想要清楚地认识Python中的群集特性与行为,认识collections.abc模块是个相当好的管道,规范抽象基础类别的PEP 3119规格书,也非常值得参考。

 

若想再更进一步,我们可以针对collectionscollections.abc中,研究相关函式或类别的程序码实现,这样将更能够掌握相关特性的实现细节。

 

清楚而自信地使用资料结构

 

Pascal之父Niklaus E. Writh曾经说过:「算法加资料结构就等于程序」,因此是否了解常用的、特性与相关的效用函式,对程序的设计影响巨大。这在我先前专栏〈开发者应认识的资料型态及效用函式〉、以及〈善用程序库中的资料结构特性〉,也曾经探讨过。

 

因此,面对像Python这类将资料结构内建为语法一部份的语言,虽然一开始用起来顺手且具有高产能,然而,最好还是循着对资料结构特性的基本认识,逐一探讨这些便捷语法背后的设计与实现,甚至必要时,可基于标准程序库提供的基础,试着自行实现相关资料结构。

 

这么一来,不但能对相关语法或程序库能有更深入的了解,且进一步地认识语言及API的相关设计哲学,在需要这些资料结构时,也才能清楚而有自信地加以运用。

 





赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论