zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Python的collections原来这么好用!

Python 这么 好用 原来 collections
2023-06-13 09:15:43 时间

collections是实现了特定目标的容器,以提供Python标准内建容器 dict , list , set , 和 tuple 的替代选择。为了让大家更好的认识,本文详细总结collections的相关知识,一起来学习吧!

Python的collections原来这么好用!插图

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

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

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

OrderedDict:字典的子类,保留了他们被添加的顺序。

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

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

ChainMap:类似字典的容器类,将多个映射集合到一个视图里面。

Counter

Counter是一个dict子类,主要是用来对你访问的对象的频率进行计数。

 import collections

 # 统计字符出现的次数

... collections.Counter(hello world)

Counter({l: 3, o: 2, h: 1, e: 1,  : 1, w: 1, r: 1, d: 1})

 # 统计单词个数

... collections.Counter(hello world hello lucy.split())

Counter({hello: 2, world: 1, lucy: 1})

常用方法:

elements():返回一个迭代器,每个元素重复计算的个数,如果一个元素的计数小于1,就会被忽略。

most_common([n]):返回一个列表,提供n个访问频率最高的元素和计数

subtract([iterable-or-mapping]):从迭代对象中减去元素,输入输出可以是0或者负数

update([iterable-or-mapping]):从迭代对象计数元素或者从另一个 映射对象 (或计数器) 添加。

 c = collections.Counter(hello world hello lucy.split())

Counter({hello: 2, world: 1, lucy: 1})

 # 获取指定对象的访问次数,也可以使用get方法

... c[hello]

 # 查看元素

... list(c.elements())

[hello, hello, world, lucy]

 c1 = collections.Counter(hello world.split())

 c2 = collections.Counter(hello lucy.split())

Counter({hello: 1, world: 1})

Counter({hello: 1, lucy: 1})

 # 追加对象,+或者c1.update(c2)

... c1+c2

Counter({hello: 2, world: 1, lucy: 1})

 # 减少对象,-或者c1.subtract(c2)

... c1-c2

Counter({world: 1})

 # 清除

... c.clear()

Counter()

defaultdict

返回一个新的类似字典的对象。defaultdict 是内置 dict 类的子类。

class collections.defaultdict([default_factory[, ...]])

 d = collections.defaultdict()

defaultdict(None, {})

 e = collections.defaultdict(str)

defaultdict( class str , {})

例子

defaultdict的一个典型用法是使用其中一种内置类型(如str、int、list或dict等)作为默认工厂,这些内置类型在没有参数调用时返回空类型。

 e = collections.defaultdict(str)

defaultdict( class str , {})

 e[hello]

defaultdict( class str , {hello: })

 # 普通字典调用不存在的键时,报错

... e1 = {}

 e1[hello]

Traceback (most recent call last):

 File " stdin ", line 1, in module 

KeyError: hello

使用 int 作为 default_factory

 fruit = collections.defaultdict(int)

 fruit[apple] = 2

 fruit

defaultdict( class int , {apple: 2})

 fruit[banana] # 没有对象时,返回0

 fruit

defaultdict( class int , {apple: 2, banana: 0})

使用 list 作为 default_factory

 s = [(yellow, 1), (blue, 2), (yellow, 3), (blue, 4), (red, 1)]

 d = collections.defaultdict(list)

 for k,v in s:

... d[k].append(v)

defaultdict( class list , {yellow: [1, 3], blue: [2, 4], red: [1]})

 d.items()

dict_items([(yellow, [1, 3]), (blue, [2, 4]), (red, [1])])

 sorted(d.items())

[(blue, [2, 4]), (red, [1]), (yellow, [1, 3])]

使用 dict 作为 default_factory

```python

 nums = collections.defaultdict(dict)

 nums[1] = { one :1}

 nums

defaultdict(, {1: { one : 1}})

 nums[2]

 nums

defaultdict(, {1: { one : 1}, 2: {}})

使用 set 作为 default_factory

```python

 types = collections.defaultdict(set)

 types[手机].add(华为)

 types[手机].add(小米)

 types[显示器].add(AOC)

 types

defaultdict( class set , {手机: {华为, 小米}, 显示器: {AOC}})

## OrderedDict

Python字典中的键的顺序是任意的,它们不受添加的顺序的控制。

collections.OrderedDict 类提供了保留他们添加顺序的字典对象。

```python

 o = collections.OrderedDict()

 o[ k1 ] = v1 

 o[ k3 ] = v3 

 o[ k2 ] = v2 

OrderedDict([( k1 , v1 ), ( k3 , v3 ), ( k2 , v2 )])

如果在已经存在的 key 上添加新的值,将会保留原来的 key 的位置,然后覆盖 value 值。

```python

 o[k1] = 666

OrderedDict([(k1, 666), (k3, v3), (k2, v2)])

 dict(o)

{k1: 666, k3: v3, k2: v2}

## namedtuple

三种定义命名元组的方法:第一个参数是命名元组的构造器(如下的:Person1,Person2,Person3)

```python

 P1 = collections.namedtuple( Person1 ,[ name , age , height ])

 P2 = collections.namedtuple( Person2 , name,age,height )

 P3 = collections.namedtuple( Person3 , name age height )

实例化命名元组

```python

 lucy = P1(lucy,23,180)

 lucy

Person1(name=lucy, age=23, height=180)

 jack = P2(jack,20,190)

 jack

Person2(name=jack, age=20, height=190)

 lucy.name # 直接通过 实例名.属性 来调用

lucy

 lucy.age

deque

collections.deque 返回一个新的双向队列对象,从左到右初始化(用方法 append()),从 iterable(迭代对象)数据创建。如果 iterable 没有指定,新队列为空。

collections.deque 队列支持线程安全,对于从两端添加(append)或者弹出(pop),复杂度O(1)。

虽然 list 对象也支持类似操作,但是这里优化了定长操作(pop(0)、insert(0,v))的开销。

如果 maxlen 没有指定或者是 None ,deque 可以增长到任意长度。否则,deque 就限定到指定最大长度。一旦限定长度的 deque 满了,当新项加入时,同样数量的项就从另一端弹出。

支持的方法:

append(x):添加x到右端。

appendleft(x):添加x到左端。

clear():清除所有元素,长度变为0。

copy():创建一份浅拷贝。

count(x):计算队列中个数等于x的元素。

extend(iterable):在队列右侧添加iterable中的元素。

extendleft(iterable):在队列左侧添加iterable中的元素,注:在左侧添加时,iterable参数的顺序将会反过来添加。

index(x[,start[,stop]]):返回第 x 个元素(从 start 开始计算,在 stop 之前)。返回第一个匹配,如果没找到的话,抛出 ValueError 。

insert(i,x):在位置 i 插入 x 。注:如果插入会导致一个限长deque超出长度 maxlen 的话,就抛出一个 IndexError 。

pop():移除最右侧的元素。

popleft():移除最左侧的元素。

remove(value):移去找到的第一个 value。没有抛出ValueError。

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

maxlen:队列的最大长度,没有限定则为None。

 d = collections.deque(maxlen=10)

deque([], maxlen=10)

 d.extend(python)

 [i.upper() for i in d]

[P, Y, T, H, O, N]

 d.append(e)

 d.appendleft(f)

 d.appendleft(g)

 d.appendleft(h)

deque([h, g, f, p, y, t, h, o, n, e], maxlen=10)

 d.appendleft(i)

deque([i, h, g, f, p, y, t, h, o, n], maxlen=10)

 d.append(m)

deque([h, g, f, p, y, t, h, o, n, m], maxlen=10)

## ChainMap

问题背景是我们有多个字典或者映射,想把它们合并成为一个单独的映射,有人说可以用update进行合并,这样做的问题就是新建了一个数据结构以致于当我们对原来的字典进行更改的时候不会同步。如果想建立一个同步的查询方法,可以使用 ChainMap。

可以用来合并两个或者更多个字典,当查询的时候,从前往后依次查询。简单使用:

```python

 d1 = { apple :1, banana :2}

 d2 = { orange :2, apple :3, pike :1}

 combined1 = collections.ChainMap(d1,d2)

 combined2 = collections.ChainMap(d2,d1)

 combined1

ChainMap({ apple : 1, banana : 2}, { orange : 2, apple : 3, pike : 1})

 combined2

ChainMap({ orange : 2, apple : 3, pike : 1}, { apple : 1, banana : 2})

 for k,v in combined1.items():

... print(k,v)

orange 2

apple 1

pike 1

banana 2

 for k,v in combined2.items():

... print(k,v)

apple 3

banana 2

orange 2

pike 1

 /code /pre 

有一个注意点就是当对ChainMap进行修改的时候总是只会对第一个字典进行修改,如果第一个字典不存在该键,会添加。

 pre code x] = 1

ChainMap({x: 1})

 b = a.new_child()

ChainMap({}, {x: 1})

 b[x] = 2

ChainMap({x: 2}, {x: 1})

 b[y] = 3

ChainMap({x: 2, y: 3}, {x: 1})

ChainMap({x: 1})

 c = a.new_child()

ChainMap({}, {x: 1})

 c[x] = 1

 c[y] = 1

ChainMap({x: 1, y: 1}, {x: 1})

 d = c.parents

ChainMap({x: 1})

 d is a

False

 d == a

 a = {x:1,z:3}

 b = {y:2,z:4}

 c = collections.ChainMap(a,b)

ChainMap({x: 1, z: 3}, {y: 2, z: 4})

 c.maps

[{x: 1, z: 3}, {y: 2, z: 4}]

 c.parents

ChainMap({y: 2, z: 4})

 c.parents.maps

[{y: 2, z: 4}]

 c.parents.parents

ChainMap({})

 c.parents.parents.parents

ChainMap({})

文章转自:Python程序员

本文链接:http://www.yunweipai.com/39453.html

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/53314.html

python程序员