Skip to content

collections

namedtuple

tuple

不可变,可迭代
拆包:

1
2
3
4
5
x, y, z = ('a', 1, False)
print(x, y, z)
"""
a 1 False
"""
1
2
3
4
5
x, *other = ('a', 1, False)
print(x, other)
"""
a [1, False]
"""
1
2
3
4
5
6
my_tuple = ('a', [1, False])
my_tuple[1].append(2)
print(my_tuple)
"""
('a', [1, False, 2])
"""

一般不建议将可变对象放到 tuple 中

tuple优势:

  • 性能优化
  • 线程安全(因为是不可变对象)
  • 可作为 dict 的 key(也是因为不可变,可哈希)
  • 拆包特性

namedtuple

1
2
3
4
5
6
7
8
namedtuple(
    typename,
    field_names,
    *,
    rename=False,
    defaults=None,
    module=None,
)

namedtuple 主要用于构建只有少数属性但是没有方法的对象,比如数据库条目

1
2
3
4
5
6
7
from collections import namedtuple
User = namedtuple('User', ['name', 'age', 'height'])
user = User(name='cai', age=666, height=666)
print(user.age, user.name, user.height)
"""
666 cai 666
"""
1
2
3
4
5
6
7
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print(p, p.x, p.y)
"""
Point(x=1, y=2) 1 2
"""

nametuple 是 tuple 的子类,占用内存和执行效率比定义简单的类要好

1
2
3
4
5
6
7
8
from collections import namedtuple
User = namedtuple('User', ['name', 'age', 'height', "edu"])
user_tuple = ('cai', 666, 2333)
user = User(*user_tuple, "lalala")
print(user.age, user.name, user.height, user.edu)
"""
666 cai 2333 lalala
"""
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from collections import namedtuple
User = namedtuple('User', ['name', 'age', 'height', "edu"])
user_dict = {
    "name": 'cai',
    'age': 666,
    'height': 2333
}
user = User(**user_dict, edu="lalala")
print(user.age, user.name, user.height, user.edu)
"""
666 cai 2333 lalala
"""

_make(iterable)

类方法从存在的序列或迭代实例创建一个新实例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from collections import namedtuple
User = namedtuple('User', ['name', 'age', 'height', "edu"])
user_tuple = ('cai', 666, 2333, "lalala")
user=User._make(user_tuple)
print(user.age, user.name, user.height, user.edu)
user_list = ['cai', 666, 2333, "lalala"]
user=User._make(user_list)
print(user.age, user.name, user.height, user.edu)
user_dict = {
    "name": 'cai',
    'age': 666,
    'height': 2333,
    'edu': 'lalal'
}
user=User._make(user_dict)
print(user.age, user.name, user.height, user.edu)
"""
666 cai 2333 lalala
666 cai 2333 lalala
age name height edu
"""

somenamedtuple._asdict()
返回一个新的 dict ,它将字段名称映射到它们对应的值

1
2
3
4
5
6
7
8
from collections import namedtuple
User = namedtuple('User', ['name', 'age', 'height', "edu"])
user_tuple = ('cai', 666, 2333, "lalala")
user=User._make(user_tuple)
print(user._asdict())
"""
OrderedDict([('name', 'cai'), ('age', 666), ('height', 2333), ('edu', 'lalala')])
"""

拆包

1
2
3
4
5
6
7
8
9
from collections import namedtuple
User = namedtuple('User', ['name', 'age', 'height', "edu"])
user_tuple = ('cai', 666, 2333, "lalala")
user=User._make(user_tuple)
name, age, *other = user
print(name, age, other)
"""
cai 666 [2333, 'lalala']
"""

defaultdict

1
2
3
4
5
6
7
8
9
users = ["a", 'b', 'c', 'a']
user_dict = {}
for user in users:
    user_dict.setdefault(user, 0)
    user_dict[user] += 1
print(user_dict)
"""
{'a': 2, 'b': 1, 'c': 1}
"""
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from collections import defaultdict
ddict = defaultdict(list)
print(ddict['cai'])
ddict = defaultdict(int)
print(ddict['cai'])
users = ['a', 'b', 'b', 'd']
for user in users:
    ddict[user] += 1
print(ddict)
"""
[]
0
defaultdict(<class 'int'>, {'cai': 0, 'a': 1, 'b': 2, 'd': 1})
"""
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from collections import defaultdict

def gen_default():
    return {
        "name": 'cai',
        'nums': 0
    }

ddict = defaultdict(gen_default)
print(ddict['lalal'])
"""
{'name': 'cai', 'nums': 0}
"""
1
2
3
4
5
6
from collections import defaultdict
ddict = defaultdict(lambda: None)
print(ddict['lalal'])
"""
None
"""

deque GIL 是线程安全的,list 不是线程安全的

Counter

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
>>> c = Counter('abcdeabcdabcaba')  # count elements from a string
>>> c.most_common(3)                # three most common elements
[('a', 5), ('b', 4), ('c', 3)]
>>> sorted(c)                       # list all unique elements
['a', 'b', 'c', 'd', 'e']
>>> ''.join(sorted(c.elements()))   # list elements with repetitions
'aaaaabbbbcccdde'
>>> sum(c.values())                 # total of all counts
15

>>> c['a']                          # count of letter 'a'
5
>>> for elem in 'shazam':           # update counts from an iterable
...     c[elem] += 1                # by adding 1 to each element's count
>>> c['a']                          # now there are seven 'a'
7
>>> del c['b']                      # remove all 'b'
>>> c['b']                          # now there are zero 'b'
0

>>> d = Counter('simsalabim')       # make another counter
>>> c.update(d)                     # add in the second counter
>>> c['a']                          # now there are nine 'a'
9

>>> c.clear()                       # empty the counter
>>> c
Counter()

>>> c = Counter('aaabbc')
>>> c['b'] -= 2                     # reduce the count of 'b' by two
>>> c.most_common()                 # 'b' is still in, but its count is zero
[('a', 3), ('c', 1), ('b', 0)]

>>> c = Counter()                           # a new, empty counter
>>> c = Counter('gallahad')                 # a new counter from an iterable
>>> c = Counter({'a': 4, 'b': 2})           # a new counter from a mapping
>>> c = Counter(a=4, b=2)                   # a new counter from keyword args

OrderedDict

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

1
2
3
4
5
6
7
8
9
from collections import OrderedDict
user_dict = OrderedDict()
user_dict['b'] = 'b'
user_dict['a'] = 'a'
user_dict['c'] = 'c'
print(user_dict)
"""
OrderedDict([('b', 'b'), ('a', 'a'), ('c', 'c')])
"""

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from collections import OrderedDict
user_dict = OrderedDict()
user_dict['b'] = 'b'
user_dict['a'] = 'a'
user_dict['c'] = 'c'
user_dict.popitem()
print(user_dict)
"""
OrderedDict([('b', 'b'), ('a', 'a')])
"""

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from collections import OrderedDict
user_dict = OrderedDict()
user_dict['b'] = 'b'
user_dict['a'] = 'a'
user_dict['c'] = 'c'
user_dict.move_to_end('b')
print(user_dict)
"""
OrderedDict([('a', 'a'), ('c', 'c'), ('b', 'b')])
"""

底层实现为循环双端链表

ChainMap

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from collections import ChainMap
user_dict1 = {'a': 'a', 'b': 'b'}
user_dict2 = {'c': '1', 'd': 2}

new_dict = ChainMap(user_dict1, user_dict2)
print(new_dict)
print(new_dict['c'])
"""
ChainMap({'a': 'a', 'b': 'b'}, {'c': '1', 'd': 2})
1
"""
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from collections import ChainMap
user_dict1 = {'a': 'a', 'b': 'b'}
user_dict2 = {'b': '1', 'd': 2}

new_dict = ChainMap(user_dict1, user_dict2)
print(new_dict)
print(new_dict['b'])
"""
ChainMap({'a': 'a', 'b': 'b'}, {'b': '1', 'd': 2})
b
"""
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from collections import ChainMap
user_dict1 = {'a': 'a', 'b': 'b'}
user_dict2 = {'b': '1', 'd': 2}

new_dict = ChainMap(user_dict1, user_dict2)
print(new_dict.maps)
new_dict.maps[0]['a'] = 'hhhh'
print(new_dict)
"""
[{'a': 'a', 'b': 'b'}, {'b': '1', 'd': 2}]
ChainMap({'a': 'hhhh', 'b': 'b'}, {'b': '1', 'd': 2})
"""

deque

deque([iterable[, maxlen]])
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 个元素(从 start 开始计算,在 stop 之前)。返回第一个匹配,如果没找到的话,升起 ValueError
insert(i, x): 在位置 i 插入 x, 如果插入会导致一个限长deque超出长度 maxlen 的话,就升起一个 IndexError
pop(): 移去并且返回一个元素,deque最右侧的那一个。如果没有元素的话,就升起 IndexError 索引错误
popleft(): 移去并且返回一个元素,deque最左侧的那一个。如果没有元素的话,就升起 IndexError 索引错误
remove(value): 移去找到的第一个 value。 如果没有的话就升起 ValueError
reverse(): 将deque逆序排列。返回 None
rotate(n=1): 向右循环移动 n 步。 如果 n 是负数,就向左循环, 如果deque不是空的,向右循环移动一步就等价于 d.appendleft(d.pop()),向左循环一步就等价于 d.append(d.popleft())

Deque对象同样提供了一个只读属性:
maxlen: Deque的最大尺寸,如果没有限定的话就是 None