前言本文继续讨论Python内置的集合模块。本期介绍工具类双端队列(Deque)、用户列表类(UserList)和UserString类。使用。我们依然采用“短平快”的模式——文字+代码,助您学得更“快、易、省”,用得上。1.DequeDeque是stack和queue的泛化(名字读作“deck”),是“double-endedqueue”的缩写。Deque支持从deque的任一侧进行线程安全、内存高效的添加和弹出操作,并且在任一方向上具有大致相同的O(1)性能。虽然列表对象支持类似的操作,但它们都针对快速定长操作进行了优化,并且会为pop(0)和insert(0,v)操作产生O(n)的内存移动成本,这会改变底层数据表示的大小和位置。导入Pythoncollections模块后,传递collections.deque([iterable[,maxlen]]),它返回一个新的deque对象,用iterable的数据从左到右初始化(使用append())。如果未指定iterable,则新双端队列为空。可选参数maxlen是双端队列的最大大小,如果未绑定则为None。如果maxlen未指定或为None,则双端队列可以增长到任意长度。否则,deque将被限制为指定的最大长度。请注意,一旦具有指定绑定长度的双端队列已满,则在添加新项目时将从另一端丢弃相应数量的项目。看下面的简单例子:###Dequefromcollectionsimportdeque#声明一个双端队列对象,用q=deque(['user','password','token'])print(q)程序的输出初始化可迭代对象如下:在上面的DQI列表中,通过传递一个列表作为参数来定义一个deque对象。现在创建另一个,但这次使用字符串:#创建一个基于字符串的包含3个项目的新双端队列对象d=deque('dqi')#遍历双端队列元素forelemind:print(elem.upper())程序运行输出如下:DQI现在看deque对象的内容:#dequecontentlistdeque_contents=list(d)print(deque_contents)#勾选最左边的一项print(d[0])#查看最右边项print(d[-1])下运行程序的结果为:['d','q','i']di接下来简单看下deque对象支持的一些方法:1)append(x):将x添加到双端队列的右侧。2)appendleft(x):将x添加到双端队列的左边。例子如下:#右边增加一个新项d.append('j')#左边增加一个新项d.appendleft('f')#显示双端队列组合性能print(d)输出结果is:deque(['f','d','q','i','j'])3)pop():从双端队列的右侧移除并返回一个元素。如果没有元素,则引发IndexError。4)popleft():从双端队列的左侧删除并返回一个元素。如果没有元素,则引发IndexError。#从右边删除项,返回对应的项rightmost=d.pop()print(rightmost)#从左边删除项,返回对应的项leftmost=d.popleft()print(leftmost)输出结果如下:jf5)clear():从双端队列中删除所有元素,使其长度为0。6)copy():创建双端队列的浅表副本。7)count(x):计算等于x的deque元素个数。8)extend(iterable):在deque的右侧,通过追加iterable参数中的元素来扩展当前对象。#一次添加多个元素d.extend('jkl')print(d)输出结果如下:deque(['d','q','i','j','k','l'])9)extendleft(iterable):在deque对象的左侧,通过追加iterable中的元素来扩展当前对象。请注意,左附加序列会导致可迭代参数中元素的顺序颠倒。如下:#extendleft()反转输入顺序d.extendleft('xyz')print(d)输出结果为:deque(['z','y','x','d','q','i','j','k','l'])10)index(x[,start[,stop]]):返回x在双端队列中的位置(在索引开始处或之后和索引之前停止)。返回第一个匹配项,如果未找到则引发ValueError。11)insert(i,x):将x插入双端队列中i的位置。如果插入会导致有界双端队列增长超过maxlen,则会引发IndexError。12)remove(value):删除第一个出现的值。如果未找到,则引发ValueError。13)rotate(n=1):将双端队列向右旋转n步。如果n为负数,则向左旋转,即向左或向右放置n个元素。例子如下:#开头dequeprint(d)#向右旋转d.rotate(1)print(d)#向左旋转d.rotate(-1)print(d)d.rotate(3)print(d)输出结果为:deque(['z','y','x','d','q','i','j','k','l'])双端队列(['l','z','y','x','d','q','i','j','k'])双端队列(['z','y','x','d','q','i','j','k','l'])deque(['j','k','l','z','y','x','d','q','i'])14)reverse()原地反转双端队列的元素并返回None。#开头是dequeprint('olddeque:',d)#反转deque中的元素new_deq=d.reverse()print('newdeque:',new_deq)#原dequeprint('olddeque:',d反转后)输出结果:olddeque:deque(['z','y','x','d','q','i','j','k','l'])newdeque:noneolddeque:deque(['l','k','j','i','q','d','x','y','z'])如输出所示,反转()方法就地反转双端队列的元素,这意味着我们原来的双端队列对象被修改了。它返回无。温馨提示:由于Deque是线程安全的,所以常用于多线程环境,如对象共享池、数据库连接池等方法,也方便控制或自定义队列中对象的上限.2.UserListUserList类用作列表对象的包装器。它是一个有用的基类,您可以自己创建类列表类来继承和覆盖其现有方法或添加新方法。通过这种方式,可以将新的行为添加到Python中的列表中。直接从列表中继承子类的能力已经部分取代了对此类的需求;但是,此类更易于使用,因为可以将基础列表作为属性进行访问。它通常的使用方式是:importcollectionsulist=collections.UserList([list])这个类模拟列表行为,其实例的内容存储在一个常规列表中,可以通过UserList实例的data属性访问.实例的内容被初始化为列表的副本,默认为空列表[]。参数列表可以是任何可迭代对象,例如真正的Python列表或UserList对象。UserList实例除了支持可变序列的方法和操作外,还提供了以下属性:data:一个真正的列表对象,用于存储UserList类的内容。假设我们要定义一个列表,其项目不允许被删除。我们可以通过继承UserList来轻松定义这样一个类:fromcollectionsimportUserList#自定义一个继承自UserList的类#该类不允许删除其包含的项#Python中List类的Delete方法:#remove()和pop()classListWithNoItemDelete(UserList):#覆盖remove()方法defremove(self,s=None):self.not_allowed()#覆盖pop()方法defpop(self,s=None):self.not_allowed()#定义一个不允许的方法defnot_allowed(self):raiseRuntimeError("Deletionnotallowed")#自定义列表对象custom_list=ListWithNoItemDelete(['a','b','c'])#尝试删除listitemoperationcustom_list.remove('b')运行上述程序,控制台输出类似如下:...raiseRuntimeError("Deletionnotallowed")RuntimeError:Deletionnotallowed建议:该类型的主要特点是参数的复制,也就是说传入的列表不会改变,同时多了一个存储属性数据,在实际应用中可以酌情使用。3.UserStringUserString类充当字符串对象的包装器。直接从str继承子类的能力已经部分取代了对此类的需求;但是,此类更易于使用,因为可以将底层字符串作为属性进行访问。它通常的使用形式:importcollectionsuserStr=collections.UserString(seq)该类模拟一个字符串对象,其实例的内容存储在一个普通的字符串对象中,可以通过UserString实例的data属性访问。实例的内容被初始化为seq的副本。seq参数可以是任何可以使用内置str()函数转换为字符串的对象。除了支持字符串方法和操作,UserString实例还提供以下属性:data:这是一个str对象,用于存储UserString类的内容。假设我们要定义自己的str类,包括concatenate()方法,可以参考下面的实现:#UserStringfromcollectionsimportUserString#定义一个继承自UserString的子类classCustomStrClass(UserString):#定义一个新方法defconcatenate(self,other=None,delimiter=''):self.data+=delimiter+other#创建自定义字符串对象custom_str=CustomStrClass('MyCustom')custom_str.concatenate('StringClass')print(custom_str)运行程序,输出结果类似如下:MyCustomStringClass总结:这个字符串最大的特点是存储了参数的副本,并且有自定义处理和数据属性的机制。一般情况下,str类就可以了。4、本文小结本期主要介绍Python集合模块中的双端队列(Deque)、用户列表(UserList)和用户字符串(UserString)。应该根据需要结合各自的特点来使用,比如deque线程安全的支持和双端操作,UserString和UserString的复制,数据存储属性等。
