python之collections库
collections库
namedtuple
namedtuple 功能讲解
namedtuple() 返回一个新的元组子类,且规定了元组的元素的个数,同时除了使用下标获取元素之外,还可以通过属性直接获取
from collections import namedtuple
User = namedtuple("User", ["name", "age", "weight"])
print(User)
user = User("admin", "20", "60")
name, age, weight = user
print(user[0])
print(name, age, weight)
print(user.name, user.age, user.weight)
print("\n")
# 输出结果如下
# admin
# admin 20 60
# admin 20 60
由以上代码可以看出,namedtuple() 相当于直接定义了一个新的类,但是这个类跟传统的定义 class 的方式又有着巨大的区别。该方式会比直接定义 class 的方式省很多空间,其次其返回值是一个 tuple,支持 tuple 的各种操场。
同时,namedtuple() 还自带两个非常好用的方法。
# 将序列直接转换为新的 tuple 对象
user = ["root", 32, 65]
user = User._make(user)
print(user)
# 输出 User(name='root', age=32, weight=65)
# 返回一个 dict
user = User("admin", 20, 60)
print(user._asdict())
# 输出 OrderedDict([('name', 'admin'), ('age', 20), ('weight', 60)])
print('\n')
namedtuple(),可命名元组。另外资料
标准的tuple类型使用数字索引来访问元素
bob = ('Bob', 30, 'male')
print("Representation:", bob) # Representation: ('Bob', 30, 'male')
jane = ('Jane', 29, 'female')
print('\nField by index:', jane[0]) # Field by index: Jane
print('\nFields by index:') # Fields by index:
for p in [bob, jane]:
print('%s is a %d year old %s' % p)
# Bob is a 30 year old male
# Jane is a 29 year old female
这种对于标准的元组访问,我们需要知道元素对应下标索引值,但当元组的元素很多时,我们可能无法知道每个元素的具体索引值,这个时候就是可命名元组登场的时候了。
nametuple 的创建是由自己的类工厂nametuple()进行创建,而不是由标准的元组来进行实例化,通过nametuple()创建类的参数包括类名称和一个包含元素名称的字符串
P = namedtuple('Person', 'name, age, gender')
print('Type of Person:', type(P)) # Type of Person: <class 'type'>
bob = P(name='Bob', age=30, gender='male')
print('\nRepresentation:', bob) # Representation: Person(name='Bob', age=30, gender='male')
print(bob.name, bob.age, bob.gender) # Bob 30 male
jane = P(name='Jane', age=29, gender='female')
print('\nField by name:', jane.name) # Field by name: Jane
print(jane.name, jane.age, jane.gender) # Jane 29 female
print('\nFields by index:')
for p in [bob, jane]:
print('%s is a %d year old %s' % p)
# Fields by index:
# Bob is a 30 year old male
# Jane is a 29 year old female
通过上面的实例可以看出,我们通过nametuple()创建了一个Person的类,并赋值给变量P,Person的类成员包括name,age,gender,并且顺序已经定了,在实例化bob这个对象的时候,对bob的属性进行了定义。这样我们在访问bob这个元组的时候就可以通过bob的属性来复制(bob.name、bob.age等)。这样就算这个元组有1000个元素我们都能通过元素的名称来访问而不用考虑元素的下标索引值。
ChainMap
ChainMap 功能讲解
ChainMap() 可以将多个字典集合到一个字典中去,对外提供一个统一的视图。注意:该操作并是不将所有字典做了一次拷贝,实际上是在多个字典的上层又进行了一次封装而已。
from collections import ChainMap
user1 = {"name": "admin", "age": "20"}
user2 = {"name": "root", "weight": 65}
users = ChainMap(user1, user2)
print(users.maps)
users.maps[0]["name"] = "tiger"
print(users.maps)
for key, value in users.items():
print(key, value)
# 输出如下
# [{'name': 'admin', 'age': '20'}, {'name': 'root', 'weight': 65}]
# [{'name': 'tiger', 'age': '20'}, {'name': 'root', 'weight': 65}]
# name tiger
# weight 65
# age 20
print('\n')
由此可见,如果 ChainMap() 中的多个字典有重复 key,查看的时候可以看到所有的 key,但遍历的时候却只会遍历 key 第一次出现的位置,其余的忽略。
同时,我们可以通过返回的新的视图来更新原来的的字典数据。进一步验证了该操作不是做的拷贝,而是直接指向原字典。
deque
deque 功能详解
dqueue 是 ”double-ended queue” 的简称,是一种类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)操作。大大加快了遍历速度
from collections import deque
q = deque([1, 2, 3])
q.append('4')
q.appendleft('0')
print(q)
print(q.popleft())
print(q)
print('\n')
# 输出如下
# deque(['0', 1, 2, 3, '4'])
# 0
# deque([1, 2, 3, '4'])
双向队列(deque)另外资料
deque 包含在文件_collections.py中,属于高性能的数据结构(High performance data structures)之一。
可以从两端添加和删除元素,常用的结构是它的简化版。
函数 | 含义 |
---|---|
append() | 队列右边添加元素 |
appendleft() | 队列左边添加元素 |
clear() | 清空队列中的所有元素 |
count() | 返回队列中包含value的个数,结果类型为 integer |
extend() | 队列右边扩展,可以是列表、元组或字典,如果是字典则将字典的key加入到deque |
extendleft() | 同extend, 在左边扩展 |
pop() | 移除并且返回队列右边的元素 |
popleft() | 移除并且返回队列左边的元素 |
remove() | 移除队列第一个出现的元素(从左往右开始的第一次出现的元素value) |
reverse() | 队列的所有元素进行反转 |
rotate(n) | 对队列的数进行移动,若n<0,则往左移动即将左边的第一个移动到最后,移动n次,n>0 往右移动 |
str1 = 'abc123cd'
dq = deque(str1)
print(dq) # deque(['a', 'b', 'c', '1', '2', '3', 'c', 'd'])
dq = deque('abc123')
dq.extend({1:10, 2:20})
dq.extendleft('L')
print(dq) # deque(['L', 'a', 'b', 'c', '1', '2', '3', 1, 2])
dq = deque([1, 2, 3, 4, 5])
dq.rotate(-1)
print(dq) # deque([2, 3, 4, 5, 1])
Counter
Counter 功能详解
Counter 可以简单理解为一个计数器,可以统计每个元素出现的次数,同样 Counter() 是需要接受一个可迭代的对象的。
from collections import Counter
animals = ["cat", "dog", "cat", "bird", "horse", "tiger", "horse", "cat"]
animals_counter = Counter(animals)
print(animals_counter)
print(animals_counter.most_common(2))
print(animals_counter.most_common())
print('\n')
# 输出如下
# Counter({'cat': 3, 'horse': 2, 'dog': 1, 'bird': 1, 'tiger': 1})
# [('cat', 3), ('horse', 2)]
# [('cat', 3), ('horse', 2), ('dog', 1), ('bird', 1), ('tiger', 1)]
# 其实一个 Counter 就是一个字典,其额外提供的 most_common() 函数通常用于求 Top k 问题。
计数器(Counter)另外资料
计数器(Counter)
Counter 作为字典(dict)的一个子类用来进行hashtable计数,将元素进行数量统计、计数后返回一个字典,键值为元素:值为元素个数。
函数 | 含义 |
---|---|
Counter() | 获取各元素的个数,返回字典 |
most_common(int) | 按照元素出现的次数进行从高到低的排序,返回前int个元素的字典 |
elements() | 返回经过计数器Counter后的元素,返回的是一个迭代器 |
update() | 和set集合的update一样,对集合进行并集更新 |
substract() | 和update类似,只是update是做加法,substract做减法,从另一个集合中减去本集合的元素 |
iteritems | 与字典dict的items类似,返回由Counter生成的字典的所有item,只是在Counter中此方法返回的是一个迭代器,而不是列表 |
iterkeys | 与字典dict的keys方法类似,返回由Counter生成的字典的所有key,只是在Counter中此方法返回的是一个迭代器,而不是列表 |
itervalues | 与字典dict的values方法类似,返回由Counter生成的字典的所有value,只是在Counter中此方法返回的是一个迭代器,而不是列表 |
from collections import *
s = 'abcbcaccbbad'
l = ['a', 'b', 'c', 'c', 'a', 'b', 'b']
d = {'2': 3, '3': 2, '17': 2}
# Counter 获取各元素的个数,返回字典
print(Counter(s)) # Counter({'b': 4, 'c': 4, 'a': 3, 'd': 1})
print(Counter(l)) # Counter({'b': 3, 'a': 2, 'c': 2})
print(Counter(d)) # Counter({'2': 3, '3': 2, '17': 2})
# most_common(int) 按照元素出现的次数从高到低的排序,返回前int个元素的字典
m1 = Counter(s)
print(m1) # Counter({'b': 4, 'c': 4, 'a': 3, 'd': 1})
print(m1.most_common(3)) # [('b', 4), ('c', 4), ('a', 3)]
e1 = Counter(s)
print(''.join(sorted(e1.elements()))) # aaabbbbccccd
e2 = Counter(d)
print(sorted(e2.elements())) # ['17', '17', '2', '2', '2', '3', '3']
u1 = Counter(s)
u1.update('123a')
print(u1) # Counter({'a': 4, 'b': 4, 'c': 4, 'd': 1, '1': 1, '2': 1, '3': 1})
sub1 = 'which'
sub2 = 'whatw'
subset = Counter(sub1)
print(subset) # Counter({'h': 2, 'w': 1, 'i': 1, 'c': 1})
subset.subtract(Counter(sub2))
print(subset) # Counter({'h': 1, 'i': 1, 'c': 1, 'w': -1, 'a': -1, 't': -1})
OrderedDict
OrderedDict 功能详解
OrderedDict 是字典的子类,保证了元素的插入顺序。在 3.7 版本下,字典同样也保证了元素的插入顺序。那相比内置字典 OrderedDict 有哪些升级呢。
算法上, OrderedDict 可以比 dict 更好地处理频繁的重新排序操作。在跟踪最近的访问这种场景(例如在 LRU cache)下非常适用。
OrderedDict 类有一个 move_to_end() 方法,可以有效地将元素移动到任一端。
from collections import OrderedDict
user = OrderedDict()
user["name"] = "admin"
user["age"] = 23
user["weight"] = 65
print(user)
user.move_to_end("name") # 将元素移动至末尾
print(user)
user.move_to_end("name", last=False) # 将元素移动至开头
print(user)
print('\n')
# 输出如下
# OrderedDict([('name', 'admin'), ('age', 23), ('weight', 65)])
# OrderedDict([('age', 23), ('weight', 65), ('name', 'admin')])
# OrderedDict([('name', 'admin'), ('age', 23), ('weight', 65)])
有序字典(OrderedDict) 另外资料
有序字典(OrderedDict)
OrderDict 叫做有序字典,也是字典类型(dict)的一个子类,是对字典的一个补充。
字典类型是一个无序的集合,如果要想将一个传统的字典类型进行排序一般会怎么做了,我们可能会将字典的键值取出来做排序后在根据键值来进行有序的输出,
看下面的一个例子:
dic1 = dict()
dic1['a'] = '123'
dic1['b'] = 'jjj'
dic1['c'] = '394'
dic1['d'] = '999'
print(dic1) # {'a': '123', 'b': 'jjj', 'c': '394', 'd': '999'}
# 方法一
dic1_key_list = []
for k in dic1.keys():
dic1_key_list.append(k)
dic1_key_list.sort()
for key in dic1_key_list:
print('dic1字典排序结果 %s:%s'%(key, dic1[key]))
print('\n')
# {'a': '123', 'b': 'jjj', 'c': '394', 'd': '999'}
# dic1字典排序结果 a:123
# dic1字典排序结果 b:jjj
# dic1字典排序结果 c:394
# dic1字典排序结果 d:999
# 方法二
dic1_list = list(dic1.items())
print(dic1_list)
dic1_list.sort(key = lambda item: item[0])
for i in range(len(dic1_list)):
print("dic1排序结果 %s: %s" % (dic1_list[i][0], dic1_list[i][1]))
print('\n')
# [('a', '123'), ('b', 'jjj'), ('c', '394'), ('d', '999')]
# dic1排序结果 a: 123
# dic1排序结果 b: jjj
# dic1排序结果 c: 394
# dic1排序结果 d: 999
# 以上为定义传统字典类型时的一个简单排序过程。 如果我们定义一个有序字典时,将不用再如此麻烦,字典顺序将按照录入顺序进行排序且不会改变。
dic2 = OrderedDict()
dic2['a'] = '123'
dic2['b'] = 'jjj'
dic2['c'] = '394'
dic2['d'] = '999'
for k, v in dic2.items():
print("有序字典:%s:%s" % (k, v))
# 有序字典:a:123
# 有序字典:b:jjj
# 有序字典:c:394
# 有序字典:d:999
以上为定义传统字典类型时的一个简单排序过程。 如果我们定义一个有序字典时,将不用再如此麻烦,字典顺序将按照录入顺序进行排序且不会改变。
dic2 = OrderedDict()
dic2['a'] = '123'
dic2['b'] = 'jjj'
dic2['c'] = '394'
dic2['d'] = '999'
for k, v in dic2.items():
print("有序字典:%s:%s" % (k, v))
# 有序字典:a:123
# 有序字典:b:jjj
# 有序字典:c:394
# 有序字典:d:999
defaultdict
defaultdict 功能详解
defaultdict 是内置 dict 类的子类。它实现了当 key 不存在是返回默认值的功能,除此之外,与内置 dict 功能完全一样。
from collections import defaultdict
default_dict = defaultdict(int)
default_dict["x"] = 10
print(default_dict["x"])
print(default_dict["y"])
print('\n')
# 输出如下
# 10
# 0
# 注意,defaultdict 的参数必须是可操作的。比如 python 内置类型,或者无参的可调用的函数。
def getUserInfo():
return {
"name": "",
"age": 0
}
default_dict = defaultdict(getUserInfo)
admin = default_dict["admin"]
print(admin)
admin["age"] = 34
print(admin)
print('\n')
# 输出如下
# {'name': '', 'age': 0}
# {'name': '', 'age': 34}
# 上述示例我们给 defaultdict 传了一个自定义函数,当字典中不存在所取 key 时返回默认的用户信息。
默认字典(defaultdict)另外资料
默认字典,是字典的一个子类,继承有字典的方法和属性,默认字典在进行定义初始化的时候可以指定字典值的默认类型:
dic = defaultdict(dict)
dic['k1'].update({'k2': 'aaa'})
print(dic)
# defaultdict(<class 'dict'>, {'k1': {'k2': 'aaa'}})
看上面的例子,字典dic在定义的时候就定义好了值为字典类型,虽然现在字典中还没有键值k1,但仍然可以执行字典的update方法。这种操作方式在传统的字典类型中是无法实现的,必须赋值以后才能进行值得更新操作,否则会报错。看一下传统的字典类型:
b = dict()
b['k1'].append('2')
# TypeError: 'type' object is not iterable
参考:
Python基础篇(十二)-- 常用模块
https://blog.csdn.net/xq151750111/article/details/124438736
Python collections 模块
https://blog.csdn.net/python36/article/details/123985615