详解Python 中的容器 collections
写在之前
我们都知道Python中内置了许多标准的数据结构,比如列表,元组,字典等。与此同时标准库还提供了一些额外的数据结构,我们可以基于它们创建所需的新数据结构。
Python附带了一个「容器」模块collections,它包含了很多的容器数据类型,今天我们来讨论其中几个常用的容器数据类型,掌握了这几个可以减少我们重复造轮子所带来的烦扰。
namedtuple
相信你已经熟悉了元组。一个元组相当于一个不可变的列表,你可以存储一个数据的序列。这里要说的namedtuple(命名元组)和元组非常像,它们都不能修改自己的数据。说完了像,那么它们有哪些地方不像呢?
作为元组,为了获取其中的数据,我们需要使用整数作为索引:
>>>people=('Rocky','python') >>>print(people[0]) Rocky
而namedtuple把元组变成了一个针对简单任务的容器,我们不必使用整数索引来访问namedtuple的数据,反而可以像用字典一样访问namedtuple。
>>>fromcollectionsimportnamedtuple >>>people=namedtuple('people','nameagelike') >>>Rocky=people(name='rocky',age=23,like='python') >>>print(Rocky) people(name='rocky',age=23,like='python') >>>print(Rocky.name) rocky
一个namedtuple有两个必须的参数:元组名称和字段名称。在上面的代码中,我们的元组名称是people,字段名称是name,age,like。nametuple让元组变的更加易读,很容易理解代码是做什么的,同样我们也不用使用整数索引来访问一个命名元组(上面代码我们用name访问了namedtuple中的数据),这让我们的代码更加容易维护。
但是你一定要记住的是,虽然它的用法很爽,但它还是一个元组!所以属性值在namedtuple中是不可变的。
我们在上面说过可以像用字典一样访问namedtuple,那么当然也可以把它转为字典,具体操作如下所示:
>>>fromcollectionsimportnamedtuple >>>people=namedtuple('people','nameagelike') >>>Rocky=people(name='rocky',age=23,like='python') >>>print(Rocky._asdict()) OrderedDict([('name','rocky'),('age',23),('like','python')])
defaultdict
我之前在使用字典的时候相当随意,只是随便dict一下就好了,然而这样使用存在一个问题:当使用的key不存在的时候会报KeyError,而defaultdict就比较厉害了,我们完全不需要检查key是否存在,所以我们能像下面这样做的随心所欲:
fromcollectionsimportdefaultdict languages=( ('rocky','python'), ('snow','c'), ('leey','java'), ('rocky','c++'), ('leey','c#') ) favourite=defaultdict(list) forname,languageinlanguages: favourite[name].append(language) print(favourite)
输出如下所示:
defaultdict(
,{'leey':['java','c#'],'rocky':['python','c++'],'snow':['c']})
然后我们再回到“键不存在,会触发KeyError异常”这个问题上来,我们先来看dict触发KeyError的例子:
my_dict={} my_dict['name']['like']='python'
输出如下:
KeyError:'name'
defaultdict则用了一个非常巧妙的方式绕过了这个问题,请看下面的操作:
importcollections language=lambda:collections.defaultdict(language) my_dict=language() my_dict['name']['like']='python'
运行一下显示正常,我们可以用json.dumps打印出my_dict的内容:
importjson print(json.dumps(my_dict))
运行结果如下:
{"name":{"like":"python"}}
Counter
Counter是一个计数器,它可以帮助我们针对某项数据进行计数,比如可以用它来统计每个人擅长的编程语言:
fromcollectionsimportCounter languages=( ('rocky','python'), ('snow','c'), ('leey','java'), ('rocky','c++'), ('leey','c#') ) cnt=Counter(nameforname,languageinlanguages) print(cnt)
运行结果如下所示:
Counter({'leey':2,'rocky':2,'snow':1})
当然我们也可以用它来统计一个文件,比如:
fromcollectionsimportCounter
withopen('test.txt','rb')asf:
line_cnt=Counter(f)
print(line_cnt)
deque
deque提供了一个双端队列,我们可以在首尾两端添加或者删除元素
想要使用deque,首先我们要从collections中导入deque模块,然后创建一个deque对象,它的用法就像我们前面学过的list一样,并且提供了类似的方法,具体如下所示:
fromcollectionsimportdeque deq=deque() deq.append(1) deq.append(2) deq.append(3) print(deq) print(len(deq)) print(deq[0]) print(deq[-1])
输出结果如下:
deque([1,2,3])
3
1
3
我们可以从两端取出数据:
fromcollectionsimportdeque deq=deque(range(5)) print('len(deq)=={}'.format(len(deq))) deq.popleft() deq.pop() print(deq)
输出的结果如下所示:
len(deq)==5
deq==deque([1,2,3])
我们也可以对这个列表的大小进行限制,当超出我们的限制的时候,数据会从另一端被pop出去,具体我们来看下面的操作:
fromcollectionsimportdeque deq=deque(maxlen=3) deq.append(1) deq.append(2) deq.append(3) print(deq) deq.append(4) print(deq)
输出的结果如下:
deque([1,2,3],maxlen=3)
deque([2,3,4],maxlen=3)
当超出maxlen的值时,最左边的数据将从队列中删除。
当然我们还可以从任意一端扩展这个双端队列中的数据:
fromcollectionsimportdeque deq=deque([1,2,3]) deq.extendleft([0]) deq.extend([4,5,6]) print(deq)
输出的结果如下所示:
deque([0,1,2,3,4,5,6])
以上就是详解Python中的容器collections的详细内容,更多关于pythoncollections的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。