【Python入门】25.常用内置模块之 集合collections

摘要:collections模块里面常用类介绍,包括nametuple、deque、defaultdict、Ordereddict、Counter


写在前面:为了更好的学习python,博主记录下自己的学习路程。本学习笔记基于廖雪峰的Python教程,如有侵权,请告知删除。欢迎与博主一起学习Pythonヽ( ̄▽ ̄)ノ


目录

  • collections
    • nametuple
    • deque
    • defaultdict
    • OrderedDict
    • Counter

collections

collections是Python内建的一个集合模块,提供了许多有用的集合类,可以说是tuple、list、dict等集合的功能补充。

nametuple

namedtuple,具名元组。由于tuple不能给元素命名,导致往往不知道该元素表达的意思,于是就有了namedtuple

namedtuple是一个函数,它可以创建一个自定义tuple类型,并规定tuple的元素个数,而且能够用属性而不是索引来引用指定元素,换而言之,就是可以给元素命名。

比如我们要用坐标来表示一个点,就可以通过namedtuple定义一个Point类型:

>>>from collections import namedtuple
>>>Point = namedtuple('Point', ['x', 'y'])     # 通过namedtuple函数定义一个Point类,并设置两个属性x,y
>>>p = Point(1, 2)                             # 创建一个Point类的实例p,赋予属性x为1,属性y为2
>>>p.x
1
>>>p.y
2

比如我们要表示一个圆,可以这样定义一个Circle类型:

Circle = namedtuple('Circle', ['x', 'y', 'r'])

需要注意的是PonitCircle的实例对象也是tuple,它具有tuple的所有特性如不变性。而namedtuple是一个函数。

>>>type(p)
<class '__main__.Point'> 
>>>isinstance(p, tuple)
True
>>>type(namedtuple)
<class 'function'> 

deque

deque,双端队列。由于list是线性储存,在数据量大时虽然可以很快地根据索引来访问元素,但是插入或删除元素的效率很低。

deque是实现可双端插入或删除元素的双端列表,提高了效率,适用于队列和栈。

>>>from collections import deque
>>>q = deque(['a', 'b', 'c'])
>>>q.append('x')                        # 右边添加元素
>>>q.appendleft('y')                    # 左边添加元素
>>>print(q)
deque(['y', 'a', 'b', 'c', 'x']) 
>>>q.pop()                              # 删除右边的第一个元素
>>>q.popleft()                          # 删除左边的第一个元素
deque(['a', 'b', 'c']) 
>>>print(q)

可见deque实现从队列的头部或尾部添加或删除元素的功能。

defaultdict

在使用dict时,如果调用的key不存在,则会抛出keyerror。如果希望key不存在时返回其他值,可以用defaultdict

>>>from collections import defaultdict
>>>dd = defaultdict(lambda: 'NO KEY')
>>>dd['key1'] = 'aaa'
>>>dd['key1']
aaa
>>>dd['key2']
NO KEY

通过defaultdict创建的对象也是dict

>>>isinstance(dd, dict)
True

OrderedDict

OrderedDict,有序字典。

在Python3.6版之前,dict是无序的,也就是dict内部存放的顺序与key放入的顺序无关:

d = dict()
d['a']='A'
d['b']='B'
d['c']='C'

for k,v in d.items():
    print(k,v)

运行结果:

a A
c C
b B

OrderedDict是有序的:

from collections import OrderedDict

od = OrderedDict()
od['a']='A'
od['b']='B'
od['c']='C'

for k,v in od.items():
    print(k,v)

运行结果:

a A 
b B 
c C 

当然,在Python3.6及之后的版本,dict也是有序的了。那么还要OrderedDict有什么用呢?其实OrderedDict还有其他功能。

我们都知道,通过popitem( )可以删除dict的元素,但只能删除最后添加的元素。

OrderedDict中,popitem( )可以设置last参数,last默认为True,即以LIFO(后进先出)的原则来删除元素;把last改为False,则以FIFO(先进先出)的原则来删除元素。

下面是实现FIFO的一个例子(代码除注释转自廖雪峰官网)

from collections import OrderedDict

class LastUpdatedOrderedDict(OrderedDict):

    def __init__(self, capacity):

        # LastUpdatedOrderedDict沿用OrderedDict类的参数定义
        super(LastUpdatedOrderedDict, self).__init__()    
        self._capacity = capacity                         # 设置容量参数

    def __setitem__(self, key, value):

        containsKey = 1 if key in self else 0             # 如果将传入的key已有,则containsKey为1,反之0
        if len(self) - containsKey >= self._capacity:     # 如果原本key数目大于等于容量,且不是传入重复的key
            last = self.popitem(last=False)               # 以先进先出的原则,移除最早添加的元素
            print('remove:', last)                        # 打印:移除最早添加的元素
        if containsKey:                  
            del self[key]                                 # 如果传入相同的key,则删除旧的key
            print('set:', (key, value))                   # 打印:设置key新的value
        else:
            print('add:', (key, value))                   # 打印:添加新key与value

我们来试一下这个新定义的类:

>>>lod = LastUpdatedOrderedDict(3)
>>>lod['a']=1                                             # 尝试添加key'a'
add: ('a', 1)                                             # 成功添加
>>>lod
LastUpdatedOrderedDict([('a', 1)]) 

>>>lod['b']=2                                             # 尝试添加key'b'
add: ('b', 2)                                             # 成功添加
>>>lod
LastUpdatedOrderedDict([('a', 1), ('b', 2)]) 

>>>lod['c']=3                                             # 尝试添加key'c'
add: ('c', 3)                                             # 成功添加
>>>lod
LastUpdatedOrderedDict([('a', 1), ('b', 2), ('c', 3)]) 

>>>lod['d']=4                                             # 尝试添加key'd'
remove: ('a', 1)                                          # 由于已达容量个数,移除最早添加的key'a'
add: ('d', 4)                                             # 继续添加key'd'
>>>lod
LastUpdatedOrderedDict([('b', 2), ('c', 3), ('d', 4)]) 

>>>lod['b']=10                                            # 尝试添加key'b'
set: ('b', 10)                                            # 由于key'b'已有,删除原有的'b',添加新的b
>>>lod
LastUpdatedOrderedDict([('d', 4), ('c', 5), ('b', 10)]) 

代码解析:我觉得必要再说明一下这行代码:

if len(self) - containsKey >= self._capacity:

len(self)是查看原本dict的元素个数,不包括将要添加的元素。在我们的设定中,len(self)只能小于等于self._capacity,不会存在大于self._capacity的情况。

当传入的key与原有的key不重复,即containsKey为0时。在len(self) == self._capacity,即原有的元素个数达到容量个数,会执行if后的缩进语句;

当传入的key与原有的key重复,即containsKey为1时。len(self) - containsKey一定是小于self._capacity的,这种情况是不会执行if后的缩进语句的。

最后说明一下OrderedDict创建的对象也是dict类,如上例创建的lod对象:

>>>isinstance(lod, dict)
True

Counter

Counter,计数器。顾名思义,Counter是一个实现计数功能的类,使用如下:

>>>from collections import Counter
>>>c = Counter()
>>>for ch in 'hello world':
...    c[ch] = c[ch] + 1
...
>>>c
Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1}) 

以上就是本节的全部内容,感谢你的阅读。

下一节内容:常用内置模块之 base64和struct

有任何问题与想法,欢迎评论与吐槽。

和博主一起学习Python吧( ̄▽ ̄)~*

你可能感兴趣的:(Python入门,学习笔记)