Python之collections模块的使用

collections模块的作用

collections模块包含除内置类型list\dict\tuple以外的其他容器数据类型。

一、collections.ChainMap连接字典

1、搜索多个字典的示例

import collections

a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}

m = collections.ChainMap(a, b)

print('Individual Values')
print('a = {}'.format(m['a']))
print('b = {}'.format(m['b']))
print('c = {}'.format(m['c']))
print()

print('Keys = {}'.format(list(m.keys())))
print('Values = {}'.format(list(m.values())))
print()

print('Items:')
for k, v in m.items():
    print('{} = {}'.format(k, v))
print()

print('"d" in m: {}'.format(('d' in m)))
collections_chainmap_read.py

运行效果

Individual Values
a = A
b = B
c = C

Keys = ['b', 'c', 'a']
Values = ['B', 'C', 'A']

Items:
b = B
c = C
a = A

"d" in m: False

2、排序字典,重新获取key-value的示例

import collections

a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}

m = collections.ChainMap(a, b)

print(m.maps)
print('c = {}\n'.format(m['c']))

# 用key排序字典
m.maps = list(reversed(m.maps))

print(m.maps)
print('c = {}'.format(m['c']))
collections_chainmap_reorder.py

运行效果

[{'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'}]
c = C

[{'b': 'B', 'c': 'D'}, {'a': 'A', 'c': 'C'}]
c = D

 3、连接字典数据的修改的示例

import collections

a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}

m = collections.ChainMap(a, b)
print('Before: {}'.format(m['c']))
a['c'] = 'E'
print('After : {}'.format(m['c']))
collections_chainmap_update_behind.py

运行效果

Before: C
After : E

4、连接字典数据的修改其实字典也会被修改示例

import collections

a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}

m = collections.ChainMap(a, b)
print('Before:', m)
m['c'] = 'E'
print('After :', m)
print('a:', a)
collections_chainmap_update_directly.py

运行效果

Before: ChainMap({'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})
After : ChainMap({'a': 'A', 'c': 'E'}, {'b': 'B', 'c': 'D'})
a: {'a': 'A', 'c': 'E'}

5、新建一个子节点,方便修改字典连的示例

import collections

a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}

m1 = collections.ChainMap(a, b)
m2 = m1.new_child()

print('m1 before:', m1)
print('m2 before:', m2)

m2['c'] = 'E'

print('m1 after:', m1)
print('m2 after:', m2)
collections_chainmap_new_child.py

运行效果

m1 before: ChainMap({'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})
m2 before: ChainMap({}, {'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})
m1 after: ChainMap({'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})
m2 after: ChainMap({'c': 'E'}, {'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})

 6、新建一个子节点,并且传参数,直接进行修改的示例

import collections

a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
c = {'c': 'E'}

m1 = collections.ChainMap(a, b)
m2 = m1.new_child(c)

print('m1["c"] = {}'.format(m1['c']))
print('m2["c"] = {}'.format(m2['c']))
collections_chainmap_new_child_explicit.py

运行效果

m1["c"] = C
m2["c"] = E

 二、统计Hashable对象的次数

 Counter是一个容器,可以统计相同值出现的次数。

7、初始化Counter容器

import collections

print(collections.Counter(['a', 'b', 'c', 'a', 'b', 'b']))
print(collections.Counter({'a': 2, 'b': 3, 'c': 1}))
print(collections.Counter(a=2, b=3, c=1))
collections_counter_init.py

运行效果

Counter({'b': 3, 'a': 2, 'c': 1})
Counter({'b': 3, 'a': 2, 'c': 1})
Counter({'b': 3, 'a': 2, 'c': 1})

8、初始化空的Counter容器,需要update来进行更新

import collections

c = collections.Counter()
print('Initial :', c)

c.update('abcdaab')
print('Sequence:', c)

c.update({'a': 1, 'd': 5})
print('Dict    :', c)
collections_counter_update.py

运行效果

Initial : Counter()
Sequence: Counter({'a': 3, 'b': 2, 'c': 1, 'd': 1})
Dict    : Counter({'d': 6, 'a': 4, 'b': 2, 'c': 1})

9、给一批数据,统计各元素访问的次数

import collections

c = collections.Counter('abcdaab')

for letter in 'abcde':
    print('{} : {}'.format(letter, c[letter]))
collections_counter_get_values.py

运行效果

a : 3
b : 2
c : 1
d : 1
e : 0

10、elements()返回迭代器里面是所有的元素

import collections

c = collections.Counter('extremely')
c['z'] = 0
print(c)
print(list(c.elements()))
collections_counter_elements.py

运行效果

Counter({'e': 3, 'x': 1, 't': 1, 'r': 1, 'm': 1, 'l': 1, 'y': 1, 'z': 0})
['e', 'e', 'e', 'x', 't', 'r', 'm', 'l', 'y']

11、most_common(N),返回出现次数最多的前N个的示例

import collections

c = collections.Counter()
with open('words', 'rt',encoding='utf-8') as f:
    for line in f:
        c.update(line.rstrip().lower())

print('Most common:')
for letter, count in c.most_common(3):
    print('{}: {:>7}'.format(letter, count))
ollections_counter_most_common.py

运行效果

Most common:
 :     674
e:     397
t:     396

12、Counter容器的算术运算

import collections

c1 = collections.Counter(['a', 'b', 'c', 'a', 'b', 'b'])
c2 = collections.Counter('alphabet')

print('C1:', c1)
print('C2:', c2)

print('\nCombined counts:')
print(c1 + c2)

print('\nSubtraction:')
print(c1 - c2)

print('\nIntersection (taking positive minimums):')
print(c1 & c2)

print('\nUnion (taking maximums):')
print(c1 | c2)
collections_counter_arithmetic.py

运行效果

C1: Counter({'b': 3, 'a': 2, 'c': 1})
C2: Counter({'a': 2, 'l': 1, 'p': 1, 'h': 1, 'b': 1, 'e': 1, 't': 1})

Combined counts:
Counter({'a': 4, 'b': 4, 'c': 1, 'l': 1, 'p': 1, 'h': 1, 'e': 1, 't': 1})

Subtraction:
Counter({'b': 2, 'c': 1})

Intersection (taking positive minimums):
Counter({'a': 2, 'b': 1})

Union (taking maximums):
Counter({'b': 3, 'a': 2, 'c': 1, 'l': 1, 'p': 1, 'h': 1, 'e': 1, 't': 1})

三、defaultdict设置一个字典默认的返回值

13、defaultdict设置一个字典默认的返回值

import collections

def default_factory():
    return 'default value'

d = collections.defaultdict(default_factory, foo='bar')
print('d:', d)
print('foo =>', d['foo'])
print('bar =>', d['bar'])
collections_defaultdict.py

运行效果

d: defaultdict(<function default_factory at 0x0000024D18064288>, {'foo': 'bar'})
foo => bar
bar => default value

四、双端队列

 作用:
  双端队列或deque支持从任意一端增加和删除元素。更为常用的两种结构(即栈和队列)就是双端队列的退化形式,它们的输入和输出被限制在某一端。

14、双端队列创建、删除、获取数据

import collections

d = collections.deque('abcdefg')
print('Deque:', d)
print('Length:', len(d))
print('Left end:', d[0])
print('Right end:', d[-1])

d.remove('c')
print('remove(c):', d)
collections_deque.py

运行效果

Deque: deque(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
Length: 7
Left end: a
Right end: g
remove(c): deque(['a', 'b', 'd', 'e', 'f', 'g'])

15、双端队列的左,右端数据的增加示例

import collections

# 增加元素到双端队列的右端
d1 = collections.deque()
d1.extend('abcdefg')
print('extend    :', d1)
d1.append('h')
print('append    :', d1)

# 增加元素到双端队列的左端
d2 = collections.deque()
d2.extendleft(range(6))
print('extendleft:', d2)
d2.appendleft(6)
print('appendleft:', d2)
collections_deque_populating.py

运行效果

extend    : deque(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
append    : deque(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
extendleft: deque([5, 4, 3, 2, 1, 0])
appendleft: deque([6, 5, 4, 3, 2, 1, 0])

16、双端队列左,右端数据的获取

import collections

print('从右往左取:')
d = collections.deque('abcdefg')
while True:
    try:
        print(d.pop(), end='')
    except IndexError:
        break
print()

print('\n从左往右取:')
d = collections.deque(range(6))
while True:
    try:
        print(d.popleft(), end='')
    except IndexError:
        break
print()
collections_deque_consuming.py

 运行效果

从右往左取:
gfedcba

从左往右取:
012345

17、双端队列是线程安全的示例

import collections
import threading
import time

candle = collections.deque(range(5))

def burn(direction, nextSource):
    while True:
        try:
            next = nextSource()
        except IndexError:
            break
        else:
            print('{:>8}: {}'.format(direction, next))
            time.sleep(0.1)
    print('{:>8} done'.format(direction))
    return

left = threading.Thread(target=burn,args=('Left', candle.popleft))
right = threading.Thread(target=burn,args=('Right', candle.pop))

left.start()
right.start()

left.join()
right.join()
collections_deque_both_ends.py

运行效果

    Left: 0
   Right: 4
    Left: 1
   Right: 3
    Left: 2
   Right done
    Left done

18、双端队列旋转,规则,正数:右出左进,负数:左出右进

import collections

d = collections.deque(range(10))
print('Normal        :', d)

d = collections.deque(range(10))
d.rotate(2)
print('Right rotation:', d)

d = collections.deque(range(10))
d.rotate(-2)
print('Left rotation :', d)
collections_deque_rotate.py

运行效果

Normal        : deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Right rotation: deque([8, 9, 0, 1, 2, 3, 4, 5, 6, 7])
Left rotation : deque([2, 3, 4, 5, 6, 7, 8, 9, 0, 1])

19、双端队列设置存储最多的数量

import collections
import random

# 设置随机种子,这样我们每次运行脚本时都会看到相同的输出
random.seed(1)

d1 = collections.deque(maxlen=3)
d2 = collections.deque(maxlen=3)

for i in range(5):
    n = random.randint(0, 100)
    print('n =', n)
    d1.append(n)
    d2.appendleft(n)
    print('D1:', d1)
    print('D2:', d2)
collections_deque_maxlen.py

运行效果

n = 17
D1: deque([17], maxlen=3)
D2: deque([17], maxlen=3)
n = 72
D1: deque([17, 72], maxlen=3)
D2: deque([72, 17], maxlen=3)
n = 97
D1: deque([17, 72, 97], maxlen=3)
D2: deque([97, 72, 17], maxlen=3)
n = 8
D1: deque([72, 97, 8], maxlen=3)
D2: deque([8, 97, 72], maxlen=3)
n = 32
D1: deque([97, 8, 32], maxlen=3)
D2: deque([32, 8, 97], maxlen=3)

 五、带命名字段的元组子类

20、普通元组的取值方式

# 取整个元组
bob = ('Bob', 30, 'male')
print('Representation:', bob)

# 取元级第一个元素
jane = ('Jane', 29, 'female')
print('\nField by index:', jane[0])

# 使用*号,打印整体的元组
print('\nFields by index:')
for p in [bob, jane]:
    print('{} is a {} year old {}'.format(*p))
collections_tuple.py

运行效果

Representation: ('Bob', 30, 'male')

Field by index: Jane

Fields by index:
Bob is a 30 year old male
Jane is a 29 year old female

21、定义命令字段的元组。collections.namedtuple(元组名字, '字段1 字段2')

import collections

Person = collections.namedtuple('Person', 'name age')

bob = Person(name='Bob', age=30)
print('\nRepresentation:', bob)

jane = Person(name='Jane', age=29)
print('\nField by name:', jane.name)

print('\nFields by index:')
for p in [bob, jane]:
    print('{} is {} years old'.format(*p))
collections_namedtuple_person.py

运行效果

Representation: Person(name='Bob', age=30)

Field by name: Jane

Fields by index:
Bob is 30 years old
Jane is 29 years old

22、命令元组属性是不可以修改的示例

import collections

Person = collections.namedtuple('Person', 'name age')

pat = Person(name='Pat', age=12)
print('\nRepresentation:', pat)

pat.age = 21
collections_namedtuple_immutable.py

运行效果

Representation: Person(name='Pat', age=12)

23、命令元组属性名有重复的时候,异常的处理

import collections

try:
    collections.namedtuple('Person', 'name class age')
except ValueError as err:
    print(err)

try:
    collections.namedtuple('Person', 'name age age')
except ValueError as err:
    print(err)
collections_namedtuple_bad_fields.py

运行效果

Type names and field names cannot be a keyword: 'class'
Encountered duplicate field name: 'age'

24、对非法字段名重复进行做下标的处理

import collections

with_class = collections.namedtuple(
    'Person', 'name class age',
    rename=True)
print(with_class._fields)

two_ages = collections.namedtuple(
    'Person', 'name age age',
    rename=True)
print(two_ages._fields)
collections_namedtuple_rename.py

运行效果

('name', '_1', 'age')
('name', 'age', '_2')

25、查看指定命令元组对象,可调用的字段名

import collections

Person = collections.namedtuple('Person', 'name age')

bob = Person(name='Bob', age=30)
print('Representation:', bob)
print('Fields:', bob._fields)
collections_namedtuple_fields.py

 运行效果

Representation: Person(name='Bob', age=30)
Fields: ('name', 'age')

26、查看指定命令元组对象,可调用的字段名,以有序字典返回

import collections

Person = collections.namedtuple('Person', 'name age')

bob = Person(name='Bob', age=30)
print('Representation:', bob)
print('As Dictionary:', bob._asdict())
collections_namedtuple_asdict.py

运行效果

Representation: Person(name='Bob', age=30)
As Dictionary: OrderedDict([('name', 'Bob'), ('age', 30)])

27、可命名元组数据的修改,其实就是修改内存对象

import collections

Person = collections.namedtuple('Person', 'name age')

bob = Person(name='Bob', age=30)
print('\nBefore:', bob)
bob2 = bob._replace(name='Robert')
print('After:', bob2)
print('Same?:', bob is bob2)
collections_namedtuple_replace.py

运行效果

Before: Person(name='Bob', age=30)
After: Person(name='Robert', age=30)
Same?: False

六、有序字典 

28、普通字典和排序字典的创建

import collections

print('普通字典:')
d = {}
d['a'] = 'A'
d['b'] = 'B'
d['c'] = 'C'

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

print('\n排序字典:')
d = collections.OrderedDict()
d['a'] = 'A'
d['b'] = 'B'
d['c'] = 'C'

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

运行效果

普通字典:
a A
b B
c C

排序字典:
a A
b B
c C

29、分别创建两个普通字典和排序字典对象内存地址的比较

import collections

print('dict       :', end=' ')
d1 = {}
d1['a'] = 'A'
d1['b'] = 'B'
d1['c'] = 'C'

d2 = {}
d2['c'] = 'C'
d2['b'] = 'B'
d2['a'] = 'A'

print(d1 == d2)

print('OrderedDict:', end=' ')

d1 = collections.OrderedDict()
d1['a'] = 'A'
d1['b'] = 'B'
d1['c'] = 'C'

d2 = collections.OrderedDict()
d2['c'] = 'C'
d2['b'] = 'B'
d2['a'] = 'A'

print(d1 == d2)
collections_ordereddict_equality.py

运行效果

dict       : True
OrderedDict: False
总结:
    有序字典,比较对象是否相等,还要判断排序的顺序

30、排序字典元素对象的移动

import collections

d = collections.OrderedDict(
    [('a', 'A'), ('b', 'B'), ('c', 'C')]
)

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

d.move_to_end('b')

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

d.move_to_end('b', last=False)

print('\nmove_to_end(last=False):')
for k, v in d.items():
    print(k, v)
collections_ordereddict_move_to_end.py

 运行效果

Before:
a A
b B
c C

move_to_end():
a A
c C
b B

move_to_end(last=False):
b B
a A
c C

七、容器的抽象基类(collections.abc)

 作用:

    该collections.abc模块包含抽象基类,这些基类定义了Python内置并由collections模块提供的容器数据结构的API 。有关类别及其用途的列表,请参见下表。

 

 

collections.abc

posted @ 2020-06-19 09:38  小粉优化大师  阅读(323)  评论(0编辑  收藏  举报