collections内建模块

Python的collections

@(Python学习-随手记)[collections, 帮助, Python]
在这里插入图片描述

  • collections 模块实现了特定目标的容器,以提供Python标准内建容器 dict , list , set , 和 tuple 的替代选择。

Counter

基础

  • Counterdict的子类,主要是用来对你访问的对象的频率进行计数
import collections

"""
Counter : 可用于对你访问的对象的频率进行计数
参数:可以是iterable-or-mapping
比如:字符串,列表,字典,或者直接通过keywords参数的形式
"""

# 统计字符出现的次数
# result: Counter({'l': 3, 'o': 2, ' ': 1, 'e': 1, 'd': 1, 'h': 1, 'r': 1, 'w': 1})
print collections.Counter("hello world")
# 统计单词出现的次数
# result: Counter({'hello': 2, 'world': 1, 'lucy': 1})
print collections.Counter("hello world hello lucy".split( ))

常用方法

  • elements():返回一个迭代器,其中每个元素将重复出现计数值所指定次数。 如果一个元素的计数值小于1,elements() 将会忽略它。
# result: ['hello', 'hello', 'lucy', 'world']
c = collections.Counter('hello world hello lucy'.split())
print sorted(c.elements())
  • most_common([n]):返回一个列表,其中包含 n 个最常见的元素及出现次数,按常见程度由高到低排序。 如果 n 被省略或为 None,most_common() 将返回计数器中的 所有 元素。 计数值相等的元素按首次出现的顺序排序
# result: [('hello', 2), ('world', 1), ('lucy', 1)]
c1= collections.Counter("abracadabra")
print c.most_common(3)
  • subtract(iterable-or-mapping):从 迭代对象 或 映射对象 减去元素,输入和输出都可以是0或者负数。【另外一种等价方式是c1-c2
    • 两者区别:
      1、subtract()不会忽略计数值小于1的元素,而-会忽略
      2、subtract()会改变原有Counter对象,而-会产生新的Counter对象
c2 = collections.Counter("hello word hello deng".split( ))
c3 = collections.Counter("hello lucy".split( ))
# result:Counter({'word': 1, 'deng': 1, 'hello': 1})
print c2 - c3
c2.subtract(c3)
# result:Counter({'deng': 1, 'word': 1, 'hello': 1, 'lucy': -1})
print c2
  • update(iterable-or-mapping):从 迭代对象 或 映射对象 添加元素,【另外一种等价方式是c1+c2
    • 两者区别:
      1、update()会改变原有Counter对象,而+会产生新的Counter对象
c1 = collections.Counter('hello world'.split())
c2 = collections.Counter('hello lucy'.split())
# Counter({'hello': 2, 'world': 1, 'lucy': 1})
print c1 + c2
c1.update(c2)
# Counter({'hello': 2, 'world': 1, 'lucy': 1})
print c1
  • clear():清除元素
c1 = collections.Counter('hello world'.split())
c1.clear()
# Counter()
print c1

defaultdict

来源

  • 当使用普通字典时,用法一般是dict={},添加元素只需要dict[element] =value,调用元素xxx=dict[element],但问题是如果element不在字典里,就会报错keyError,如下:
dict = {}
dict["name"] = "lucy"
# result : lucy
print dict["name"]
# result:KeyError: 'age'
print dict["age"]
  • defaultdict的作用就是当字典中key不存在但被查找时,返回的不是keyError而是一个默认值

使用方式

  • defaultdict接受一个工厂函数作为参数:dict =defaultdict(factory_function),返回一个新的类似字典的对象, defaultdict是内置 dict 类的子类。
  • factory_function可以是list,set,str等等,作用是当key不存在时,返回的是工厂函数的默认值,比如list对用的[],str对应的空字符串,set对应的是set(),int对应的是0
from collections import defaultdict
dict1 = defaultdict(int)
dict2 = defaultdict(set)
dict3 = defaultdict(list)
dict4 = defaultdict(dict)

dict1[2] = "two"

# result:0
print dict1[1]
# result:set([])
print dict2[1]
# result: []
print dict3[1]
# result: {}
print dict4[1]

使用list作为工厂函数


from collections import defaultdict, Counter

dict = defaultdict(list)
# 定义key-value 组成的列表
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]

# 转换成key-[]的字典
for k,v in s:
    dict[k].append(v)
# result:defaultdict(<type 'list'>, {'blue': [2, 4], 'red': [1], 'yellow': [1, 3]})
print dict

deque

基础

  • collections.deque([iterable[, maxlen]])返回一个新的双向队列对象,从左向右初始化(方法append()),从iterable迭代对象数据创建,如果iterable没有指定,新队列为空
  • Deque队列是由栈或者queue队列生成的(发音是 “deck”,”double-ended queue”的简称)。Deque 支持线程安全,内存高效添加(append)和弹出(pop),从两端都可以,两个方向的大概开销都是 O(1) 复杂度。
  • 虽然 list 对象也支持类似操作,不过这里优化了定长操作和 pop(0) 和 insert(0, v) 的开销。它们引起 O(n) 内存移动的操作,改变底层数据表达的大小和位置。
  • 如果 maxlen 没有指定或者是 None ,deques 可以增长到任意长度。否则,deque就限定到指定最大长度。一旦限定长度的deque满了,当新项加入时,同样数量的项就从另一端弹出。限定长度deque提供类似Unix filter tail 的功能。它们同样可以用与追踪最近的交换和其他数据池活动。
  • 常用方法

append(x)
添加 x 到右端。

appendleft(x)
添加 x 到左端。

clear()
移除所有元素,使其长度为0.

copy()
创建一份浅拷贝。

3.5 新版功能.

count(x)
计算 deque 中元素等于 x 的个数。

3.2 新版功能.

extend(iterable)
扩展deque的右侧,通过添加iterable参数中的元素。

extendleft(iterable)
扩展deque的左侧,通过添加iterable参数中的元素。注意,左添加时,在结果中iterable参数中的顺序将被反过来添加。

index(x[, start[, stop]])
返回 x 在 deque 中的位置(在索引 start 之后,索引 stop 之前)。 返回第一个匹配项,如果未找到则引发 ValueError。

3.5 新版功能.

insert(i, x)
在位置 i 插入 x 。

如果插入会导致一个限长 deque 超出长度 maxlen 的话,就引发一个 IndexError。

3.5 新版功能.

pop()
移去并且返回一个元素,deque 最右侧的那一个。 如果没有元素的话,就引发一个 IndexError。

popleft()
移去并且返回一个元素,deque 最左侧的那一个。 如果没有元素的话,就引发 IndexError。

remove(value)
移除找到的第一个 value。 如果没有的话就引发 ValueError。

reverse()
将deque逆序排列。返回 None 。

3.2 新版功能.

rotate(n=1)
向右循环移动 n 步。 如果 n 是负数,就向左循环。

如果deque不是空的,向右循环移动一步就等价于 d.appendleft(d.pop()) , 向左循环一步就等价于 d.append(d.popleft()) 。

Deque对象同样提供了一个只读属性:

maxlen
Deque的最大尺寸,如果没有限定的话就是 None 。

相关资料

python的deque(双向)队列详解

ChainMap

由来

  • 问题的背景是我们有多个字典或者映射,想把它们合并成为一个单独的映射,有人说可以用update进行合并,这样做的问题就是新建了一个数据结构以致于当我们对原来的字典进行更改的时候不会同步。如果想建立一个同步的查询方法,可以使用ChainMap
  • python内置函数ChainMap可以将多个字典合并为一个独有的字典,这样的操作 并不是对源数据的拷贝,而是在内部储存一个Key到每个字典的映射,当你读取 e[key] 的时候,它先去查询这个key在哪个字典里面,然后再去对应的字典里面查询对应的值。
  • 使用ChainMap几乎不需要额外的内存空间(当前这个对象自己会占用一些空间,但是如果要合并大字典,那么它自己占用的空间几乎可以忽略

初步使用


from chainmap import ChainMap

a = {"x":1, "z":3}
b = {"y":2, "z":4}

c = ChainMap(a,b)
# result:ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4})
print c
# 读取数据
# result:1
print c.get("x")
# result:2
print c.get("y")
# result:3
print c.get("z")

结论一:修改原始字典,查看ChainMap对象会同步

from chainmap import ChainMap

a = {"x":1, "z":3}
b = {"y":2, "z":4}

c = ChainMap(a,b)
# result:ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4})
print c
# 修改数据
a["x"] = "5"
# result ChainMap({'x': '5', 'z': 3}, {'y': 2, 'z': 4})
print c

结论二:ChainMap实际上是把放入的字典存储在一个队列中,当进行字典的增加删除更新等操作只会在第一个字典上进行,当进行查找的时候会依次查找,返回第一个查询到的值

#!/use/bin/python
# -*- coding: utf-8 -*-
"""
    @Author : bd
    @Create : 2021/1/26 下午10:38
    @Package: Collections_Demo.py
    @Description:
    @software:PyCharm
"""

from chainmap import ChainMap

a = {"x":1, "z":3}
b = {"y":2, "z":4}

c = ChainMap(a,b)
# result:ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4})
print c
# pop数据
a.pop("z")
# result ChainMap({'x': 1}, {'y': 2, 'z': 4})
print c

c["z"] = 5
# result: ChainMap({'x': 1, 'z': 5}, {'y': 2, 'z': 4})
print c

c["z"] = 6
# result ChainMap({'x': 1, 'z': 6}, {'y': 2, 'z': 4})
print c

结论三:ChainMap查询和遍历和普通字典遍历一样,当进行查找的时候会依次查找,返回第一个查询到的值

from chainmap import ChainMap

dict1 = {"a": "zhangsan", "b": "lisi"}
dict2 = {"c": "wangwu"}
dict3 = {"d": "liqui", "b": "laowang"}
dict4 = ChainMap(dict1,dict2,dict3)

for k,v in dict4.items():
    """
    result:
        k:a;v:zhangsan
        k:c;v:wangwu
        k:b;v:laowang
        k:d;v:liqui
    """
    print "k:{};v:{}".format(k,v)

结论四:如果在使用ChainMap合并多个字典时,字典中有重复的key值,默认取第一个字典中key对用的value

结论五:maps 方法会将串联起来的字典以列表的形式展示

from chainmap import ChainMap

dict1 = {"a": "zhangsan", "b": "lisi"}

dict2 = {"c": "wangwu"}

dict3 = {"d": "liqui", "b": "laowang"}

new_dict = ChainMap(dict1, dict2, dict3)
# new_dict 修改之前:ChainMap({'a': 'zhangsan', 'b': 'lisi'}, {'c': 'wangwu'}, {'b': 'laowang', 'd': 'liqui'})
# dict1 修改之前:{'a': 'zhangsan', 'b': 'lisi'}:
print "new_dict 修改之前:{}".format(new_dict)
print("dict1 修改之前:{}:".format(dict1))

# 操作列表中索引值为0的字典,修改key="a"对应的value

new_dict.maps[0]["a"] = 18
# new_dict 修改之后:ChainMap({'a': 18, 'b': 'lisi'}, {'c': 'wangwu'}, {'b': 'laowang', 'd': 'liqui'})
# dict1 修改之前:后:{'a': 18, 'b': 'lisi'}

print "new_dict 修改之后:{}".format(new_dict)
print("dict1 修改之前:后:{}".format(dict1))
from chainmap import ChainMap

dict1 = {"a": "zhangsan", "b": "lisi"}
dict2 = {"c": "wangwu"}
dict3 = {"d": "liqui", "b": "laowang"}

new_dict = ChainMap(dict1, dict2, dict3)
# new_dict 修改之前:ChainMap({'a': 'zhangsan', 'b': 'lisi'}, {'c': 'wangwu'}, {'b': 'laowang', 'd': 'liqui'})
print "new_dict 修改之前:{}".format(new_dict)

# [{'a': 'zhangsan', 'b': 'lisi'}, {'c': 'wangwu'}, {'b': 'laowang', 'd': 'liqui'}]
print new_dict.maps

# 修改dict3 中指定键的值
new_dict.maps[2]["b"] = "dengbiao"

# new_dict 修改之后:ChainMap({'a': 'zhangsan', 'b': 'lisi'}, {'c': 'wangwu'}, {'b': 'dengbiao', 'd': 'liqui'})
print "new_dict 修改之后:{}".format(new_dict)

结论六:ChainMap使用就是原始字典,共用同一内存地址,因此原始数据修改,ChainMap映射也会改变;如果对ChainMap的结果修改,那么原数据一样也会被修改

结论七:new_child()方法实质上是在列表的第一个元素前放入一个字典,默认是{}

from chainmap import ChainMap

dict1 = {"a": "zhangsan", "b": "lisi"}
dict2 = {"c": "wangwu"}
dict3 = {"d": "liqui", "b": "laowang"}

new_dict = ChainMap(dict1, dict2, dict3)
# new_dict 修改之前:ChainMap({'a': 'zhangsan', 'b': 'lisi'}, {'c': 'wangwu'}, {'b': 'laowang', 'd': 'liqui'})
print "new_dict 修改之前:{}".format(new_dict)
# [{'a': 'zhangsan', 'b': 'lisi'}, {'c': 'wangwu'}, {'b': 'laowang', 'd': 'liqui'}]
print new_dict.maps

new_dict2 = new_dict.new_child({"e":"dengbiao"})
# result :ChainMap({'e': 'dengbiao'}, {'a': 'zhangsan', 'b': 'lisi'}, {'c': 'wangwu'}, {'b': 'laowang', 'd': 'liqui'})
print new_dict2

相关资料

在Python中合并字典模块ChainMap的隐藏坑

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值