python容器数据类型 --- collections 详解

collections 是python3中的一个标准库,提供了9种容器用来解决特定的问题

namedtuple()

创建命名元组子类的工厂函数

deque

类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)

ChainMap

类似字典(dict)的容器类,将多个映射集合到一个视图里面

Counter

字典的子类,提供了可哈希对象的计数功能

OrderedDict

字典的子类,保存了他们被添加的顺序

defaultdict

字典的子类,提供了一个工厂函数,为字典查询提供一个默认值

UserDict

封装了字典对象,简化了字典子类化

UserList

封装了列表对象,简化了列表子类化

UserString

封装了字符串对象,简化了字符串子类化

本篇文章来讲collectons中常用的对象:CounterOrderedDictdefaultdictnamedtupledeque

Counter 对象

counter是一个计数器类,可以统计字符串、字典、元组、列表等对象中每个值的次数

一个 Counter 是一个 dict 的子类,用于计数可哈希对象。它是一个集合,元素像字典键(key)一样存储,它们的计数存储为值。计数可以是任何整数值,包括0和负数。

from collections import Counter

c = Counter()                           # a new, empty counter
c = Counter('gallahad')                 # a new counter from an iterable
c = Counter({'red': 4, 'blue': 2})      # a new counter from a mapping
c = Counter(cats=4, dogs=8)             # a new counter from keyword args

Counter对象有一个字典接口,如果引用的键没有任何记录,就返回一个0,而不是弹出一个 KeyError :

>>> c = Counter(['eggs', 'ham'])
>>> c['dog']                              # count of a missing element is zero
0

注:从计数器中移去一个元素,使用 del 来删除它: del c['key']

常用方法

most_common([n])

        返回一个列表,其中包含 n 个最常见的元素及出现次数,按常见程度由高到低排序。 如果 n 被省略或为 Nonemost_common() 将返回计数器中的 所有 元素。 计数值相等的元素按首次出现的顺序排序:

>>> # 计算字符串abracadabra中出现最多的3个字母
>>> Counter('abracadabra').most_common(3)
[('a', 5), ('b', 2), ('r', 2)]

elements()

        返回一个迭代器,其中每个元素将重复出现计数值所指定次。 元素会按首次出现的顺序返回。 如果一个元素的计数值小于一,elements() 将会忽略它。

>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> sorted(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']

subtract([iterable-or-mapping])

        从 迭代对象 或 映射对象 减去元素。像 dict.update() 但是是减去,而不是替换。输入和输出都可以是0或者负数。

>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> d = Counter(a=1, b=2, c=3, d=4)
>>> c.subtract(d)
>>> c
Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})

update([iterable-or-mapping])

        从 迭代对象 计数元素或者 从另一个 映射对象 (或计数器) 添加。 像 dict.update() 但是是加上,而不是替换。另外,迭代对象 应该是序列元素,而不是一个 (key, value) 对。

>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> d = Counter(a=1, b=2, c=3, d=4)
>>> c.update(d)
>>> c
Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2})

Counter 对象的常用案例:

sum(c.values())                 # 统计总的次数
c.clear()                       # 重置次数
list(c)                         # 以list的形式列出唯一的元素
set(c)                          # 以set的形式列出唯一的元素
dict(c)                         # 转换成普通字典
c.items()                       # 转换成元组(元素、次数)的形式列表
Counter(dict(list_of_pairs))    # 从(元素、次数)对列表转换
+c                              # 移除次数为0或者负数的元素

        提供了几个数学操作,可以结合 Counter 对象,以生产 multisets (计数器中大于0的元素)。 加和减,结合计数器,通过加上或者减去元素的相应计数。交集和并集返回相应计数的最小或最大值。每种操作都可以接受带符号的计数,但是输出会忽略掉结果为零或者小于零的计数。

>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d                       # add two counters together:  c[x] + d[x]
Counter({'a': 4, 'b': 3})
>>> c - d                       # subtract (keeping only positive counts)
Counter({'a': 2})
>>> c & d                       # intersection:  min(c[x], d[x]) 
Counter({'a': 1, 'b': 1})
>>> c | d                       # union:  max(c[x], d[x])
Counter({'a': 3, 'b': 2})

defaultdict 对象

        原生内置类dict的对象在访问不存在的key时,放发生异常KeyError异常,而不想要发生异常则可以使用defaultdict对象。

class collections.defaultdict(default_factory=None, /[, ...])

default_factory

        如果构造对象时提供了第一个参数,则本属性会被初始化成那个参数,如果未提供第一个参数,则本属性为 None

        返回一个新的类似字典的对象。 defaultdict 是内置 dict 类的子类。 它重载了一个方法并添加了一个可写的实例变量。 其余的功能与 dict 类相同因而不在此文档中写明。本对象包含一个名为 default_factory 的属性,该属性的值可以是list、dict、set等等。

>>>  # 访问不存在的key:a
>>> defaultdict(int)['a']     # 0
>>> defaultdict(set)['a']     # set()
>>> defaultdict(dict)['a']    # {}
>>> defaultdict(list)['a']    # []

使用 list 作为 default_factory,很轻松地将(键-值对组成的)序列转换为(键-列表组成的)字典:

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
        d[k].append(v)

>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

        当每个键第一次遇见时,它还没有在字典里面,所以自动创建该条目,即调用 default_factory 方法,返回一个空的 list。 list.append() 操作添加值到这个新的列表里。当再次存取该键时,就正常操作,list.append() 添加另一个值到列表中。这个计数比它的等价方法 dict.setdefault() 要快速和简单

        设置 default_factory 为 int,使 defaultdict 用于计数(类似其他语言中的 bag 或 multiset):

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
        d[k] += 1

>>> sorted(d.items())
[('i', 4), ('m', 1), ('p', 2), ('s', 4)]

OrderedDict 对象

在python3.6版本之前,内置类dict是无序的,3.6版本之后dict是有序的,这个里的有序指的是key,vaule定义的顺序,如:

>>> # 在python3.6之前版本中,按顺序对key:a,b,c赋值,但输出顺序是无序的
>>> d = dict()
>>> d['a'] = 1
>>> d['b'] = 2
>>> d['c'] = 3
>>> d
{'a':1. 'c':3, 'b':2}

>>> # 在python3.6及以后的版本中,输出顺序是有序的
>>> d = dict()
>>> d['a'] = 1
>>> d['b'] = 2
>>> d['c'] = 3
>>> d
{'a':1. 'b':2, 'c':3}

orderedDict有序词典就像常规词典一样,但有一些与排序操作相关的额外功能。由于内置的 dict 类获得了记住插入顺序的能力(在 Python 3.7 中保证了这种新行为),它们变得不那么重要了。 

一些与 dict 的不同仍然存在:

  • 常规的 dict 被设计为非常擅长映射操作。 跟踪插入顺序是次要的。

  • OrderedDict 旨在擅长重新排序操作。 空间效率、迭代速度和更新操作的性能是次要的。

  • 算法上, OrderedDict 可以比 dict 更好地处理频繁的重新排序操作。 这使其适用于跟踪最近的访问(例如在 LRU cache 中)。

  • 对于 OrderedDict ,相等操作检查匹配顺序。

  • OrderedDict 类的 popitem() 方法有不同的签名。它接受一个可选参数来指定弹出哪个元素。

  • OrderedDict 类有一个 move_to_end() 方法,可以有效地将元素移动到任一端。

  • Python 3.8之前, dict 缺少 __reversed__() 方法。

常用方法

popitem(last=True)

        有序字典的 popitem() 方法移除并返回一个 (key, value) 键值对。 如果 last 值为真,则按 LIFO 后进先出的顺序返回键值对,否则就按 FIFO 先进先出的顺序返回键值对。

move_to_end(keylast=True)

        将现有 key 移动到有序字典的任一端。 如果 last 为真值(默认)则将元素移至末尾;如果 last 为假值则将元素移至开头。如果 key 不存在则会触发 KeyError:

>>> d = OrderedDict.fromkeys('abcde')
>>> d
OrderedDict([('a', None), ('b', None), ('c', None), ('d', None), ('e', None)])
>>> d.move_to_end('b')
>>> ''.join(d.keys())
'acdeb'
>>> d.move_to_end('b', last=False)
>>> ''.join(d.keys())
'bacde'

OrderedDict 例子和用法

        创建记住键值 最后 插入顺序的有序字典变体很简单。 如果新条目覆盖现有条目,则原始插入位置将更改并移至末尾 :

class LastUpdatedOrderedDict(OrderedDict):
    'Store items in the order the keys were last added'

    def __setitem__(self, key, value):
        super().__setitem__(key, value)
        self.move_to_end(key)

if __name__ == '__main__':
    
    d = LastUpdatedOrderedDict()
    d['a'] = 1
    d['b'] = 2
    d['c'] = 3
    print("".join(d.keys()))  # 输出 abc
    d['a'] = 1                # 重新给a复制
    print("".join(d.keys()))  # 输出 bca

        一个 OrderedDict 对于实现 functools.lru_cache() 的变体也很有用:

        LRU是操作系统的一种页面置换算法,最近经常不使用算法。

class LRU:

    def __init__(self, func, maxsize=128):
        self.func = func
        self.maxsize = maxsize
        self.cache = OrderedDict()

    def __call__(self, *args):
        if args in self.cache:
            value = self.cache[args]
            self.cache.move_to_end(args)
            return value
        value = self.func(*args)
        if len(self.cache) >= self.maxsize:
            self.cache.popitem(False)
        self.cache[args] = value
        return value

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大帅不是我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值