collections

对python内建容器dict、list、set、tuple的补充

namedtuple 命名元组
deque 队列
ChainMap 类似字典的类,用于创建包含多个映射的单个视图 包含多个自典的类
Counter 计数hashable对象的字典子类
OrderedDict 有序字典
defaultdict 具有默认值的字典
UserDict 封装了字典对象,简化了字典子类化
UserList 封装了列表对象,简化了列表子类化
UserString 封装了字符串对象,简化了字符串子类化

ChainMap

ChainMap 类将多个映射迅速地链到一起,这样它们就可以作为一个单元处理。这通常比创建一个新字典再重复地使用update() 要快得多。

class collections.ChainMap(*maps)
maps
一个可以更新的映射列表。这个列表是按照第一次搜索到最后一次搜索的顺序组织的。它是仅有 的存储状态,可以被修改。列表最少包含一个映射
**new_child(m=None, kwargs)
返回一个新的ChainMap,其中包含一个新的映射,后面跟随当前实例中的所有映射。如果指定 了 m,它会成为新的映射加在映射列表的前面;如果未指定,则会使用一个空字典,因此调用 d.new_child() 就等价于 ChainMap({}, d.maps)。如果指定了任何关键字参数,它们会 更新所传入的映射或新的空字典。此方法被用于创建子上下文,它可在不改变任何上级映射的情 况下被更新。
parents
属性返回一个新的ChainMap 包含所有的当前实例的映射,除了第一个。这样可以在搜索的时候跳过第一个映射。使用的场景类似在nested scopes 嵌套作用域中使用nonlocal 关键词.用例也可以类比内建函数super().一个d.parents的引用等价于ChainMap(
d.maps[1:])

from collections import ChainMap
baseline = {'music': 'bach', 'art': 'rembrandt'}
adjustments = {'art': 'van gogh', 'opera': 'carmen'}
my_chainMap = ChainMap(adjustments, baseline)
print(my_chainMap)  # ChainMap({'art': 'van gogh', 'opera': 'carmen'}, {'music': 'bach', 'art': 'rembrandt'})
print(list(my_chainMap))    # ['music', 'art', 'opera'] 迭代顺序是通过从后往前扫描所有映射来确定的
print(my_chainMap.new_child())  # ChainMap({}, {'art': 'van gogh', 'opera': 'carmen'}, {'music': 'bach', 'art': 'rembrandt'})
print(my_chainMap.parents)  # ChainMap({'music': 'bach', 'art': 'rembrandt'})

ChainMap类只更新链中的第一个映射,但 lookup 会搜索整个链。然而,如果需要深度写和删除,也可以很容易的通过定义一个子类来实现它

from collections import ChainMap
class DeepChainMap(ChainMap):
    def __setitem__(self, key, value):
        for mapping in self.maps:
            if key in mapping:
                mapping[key] = value
                return
        self.maps[0][key] = value
    def __delitem__(self, key):
        for mapping in self.maps:
            if key in mapping:
                del mapping[key]
                return
        raise KeyError(key)
d = DeepChainMap({'zebra': 'black'}, {'elephant': 'blue'}, {'lion': 'yellow'})
d['lion'] = 'orange' # update an existing key two levels down
d['snake'] = 'red' # new keys get added to the topmost dict
del d['elephant'] # remove an existing key one level down
print(d)    # DeepChainMap({'zebra': 'black', 'snake': 'red'}, {}, {'lion': 'orange'})

Counter

from collections import Counter
cnt = Counter()
for word in ('red', 'black', 'red', 'blue', 'red', 'black'):
    cnt[word] += 1
print(cnt)  # Counter({'red': 3, 'black': 2, 'blue': 1})

class collections.Counter([iterable-or-mapping ])
计数可以是任何整数,包括零或负的计数值
如果查询的键不在 Counter 中,它会返回一个 0 而不是引 发一个KeyError
设置一个计数为 0 不会从计数器中移去一个元素。使用 del 来删除它
在 3.7 版本发生变更: 作为dict 的子类,Counter 继承了记住插入顺序的功能。Counter 对象间的数学 运算也是保序的。结果首先把左操作数中存在的元素按照它们在左操作数中的顺序排序,后面跟着其 它元素,按它们在右操作数中的顺序排序
elements
返回一个迭代器,其中每个元素将重复出现计数值所指定次。元素会按首次出现的顺序返回。如 果一个元素的计数值小于一,elements() 将会忽略它
most_common([n ]
返回一个列表,其中包含n 个最常见的元素及出现次数,按常见程度由高到低排序。如果n被省略或为None,most_common()将返回计数器中的所有元素。计数值相等的元素按首次出现的顺序排序
subtract([iterable-or-mapping ])
减去一个可迭代对象或映射对象 (或 counter) 中的元素。
tatol()

数学运算来合并Counter

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

在给定数量和集合元素枚举所有不同的多集合,参考itertools.combinations_with_replacement()

map(Counter, combinations_with_replacement('ABC', 2)) # AA AB AC BB BC CC

deque

class collections.deque([iterable[, maxlen ]])
返回一个新的双向队列对象,从左到右初始化 (用方法append()) ,从iterable(迭代对象) 数据创建。如果iterable没有指定,新队列为空。
如果maxlen没有指定或者是None ,deques可以增长到任意长度。否则,deque就限定到指定最大长度。一旦限定长度的deque满了,当新项加入时,同样数量的项就从另一端弹出。
append(x) 添加x到右端
appendleft(x) 添加x到左端
clear() 移除所有元素,使其长度为0
copy() 创建一份浅拷贝
count(x) 计算deque中元素等于x的个数
extend(iterable) 扩展 deque 的右侧,通过添加 iterable 参数中的元素
extendleft(iterable) 扩展 deque 的左侧,通过添加 iterable 参数中的元素。注意,左添加时,在结果中 iterable 参数中的顺序将被反过来添加
index(x[,start[, stop]]) 返回x在deque中的位置(在索引start之后,索引stop之前)。返回第一个匹配项,如果未找到则引发ValueError。
insert(i, x) 在位置i插入x
pop() 移去并且返回一个元素,deque 最右侧的那一个
popleft() 移去并且返回一个元素,deque 最左侧的那一个
remove(value) 移除找到的第一个value
reverse() 将deque逆序排列
rotate(n=1) 向右循环移动 n 步。如果 n 是负数,就向左循环
maxlen Deque 的最大尺寸,如果没有限定的话就是 None

deque用法

类似unix tail过了功能

def tail(filename, n=10):
    'return the last n lines of a file'
    with open(filename) as f:
        return deque(f, n)

维护一个近期添加元素的序列,通过从左到右添加和从左边弹出

def moving_average(iterable, n=3):
    it = iter(iterable)
    d = deque(itertools.islice(it, n-1))
    d.appendleft(0)
    s = sum(d)
    for elem in it:
        s += elem - d.popleft
        d.append(elem)
        yield s/n

实现轮询调度器

def roundrobin(*iterables):
   "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    iterators = deque(map(iter, iterables))
    while iterators:
        try:
            while True:
                yield next(iterators[0])
                iterators.rotate(-1)
        except StopIteration:
            iterators.popleft()

defaultdict

class collections.defaultdict(default_factory=None, /[, ... ])
返回一个新的类似字典的对象。defaultdict是内置dict 类的子类。它重写了一个方法并添加了一个可写的实例变量
本对象包含一个名为default_factory的属性,构造时,第一个参数用于为该属性提供初始值,默认为 None。所有其他参数(包括关键字参数)都相当于传递给dict 的构造函数
missing
如果default_factory 属性为 None,则调用本方法会抛出KeyError 异常,附带参数key。 如果default_factory 不为 None,则它会被(不带参数地)调用来为 key 提供一个默认值,这 个值和 key 作为一对键值对被插入到字典中,并作为本方法的返回值返回。 如果调用default_factory 时抛出了异常,这个异常会原封不动地向外层传递。 当请求的键未找到时本方法会被dict 类的 getitem() 方法调用;它返回或引发的任何对象都会被 getitem() 返回或引发。 请注意除了 getitem() 之外__missing__() 不会被调用进行任何操作。这意味着 get() 会像普通字典一样返回 None 作为默认值而不是使用default_factory

namedtuple

*collections.namedtuple(typename, field_names, , rename=False, defaults=None, module=None)
返回一个新的元组子类,名为 typename 。这个新的子类用于创建类元组的对象,可以通过字段名来获 取属性值,同样也可以通过索引和迭代获取值。

Point = namedtuple('Point', ['x', 'y'])
p = Point(11, y=22)
print(p[0] + p[1])
x, y = p
print(x, y)
print(p.x + p.y)
print(p)
p = Point._make([11, 33])
print(p)
p._asdict()
print(p)
p._replace(x=55)
print(p)
print(p._fields)
33
11 22
33
Point(x=11, y=22)
Point(x=11, y=33)
{'x': 11, 'y': 33}
Point(x=55, y=33)
('x', 'y')

转换一个字典到命名元组,使用 ** 两星操作符

a = {'x': 11, 'y': 22}
Point(**a)
posted @   且任荣枯  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 本地部署 DeepSeek:小白也能轻松搞定!
· 传国玉玺易主,ai.com竟然跳转到国产AI
· 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)
· 我们是如何解决abp身上的几个痛点
· 如何基于DeepSeek开展AI项目
点击右上角即可分享
微信分享提示