Python中collections模块(高性能集合操作)的用法详解
序号 | 方法 | 功能 | 返回值类型 | 示例 |
---|---|---|---|---|
1 | namedtuple() | 定义了一个返回值为tuple的类 。
| tuple |
|
2 | ChainMap() | 将多个字典集合到一个字典,并对外提供一个统一视图 。 | dict |
|
3 | deque() | 一种类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)操作。 | list |
|
4 | Counter() | 一个计数器,可以统计每个元素出现的次数 | dict |
|
5 | OrderedDict() | 是字典的子类,保证了元素的插入顺序 | dict |
|
6 | defaultdict() | 内置 dict 类的子类,它实现了当 key 不存在时返回默认值的功能 | dict |
|
绪论
Python中内置了4种数据类型,包括:list
,tuple
,set
,dict
,这些数据类型都有其各自的特点,但是这些特点(比如dict无序)在一定程度上对数据类型的使用产生了约束,在某些使用场景下效率会比较低,比如:有时候我们可能需要维护一个有序的字典等情况。
在这种场景下我们可以使用Python内建的collections模块
,它包括了很多有用的集合类
,合理的使用可以提高我们代码的运行效率。
0.0 collections模块的信息检索
1、查看collections模块的定义路径:collections.__file__
典型范例:
import collections
# 查看属性:__file__:查看collections模块的定义路径
collections.__file__
>>>
'/Users/zhang/opt/miniconda3/envs/py37tf114/lib/python3.7/collections/__init__.py'
2、查看collections文档介绍信息:collections.__doc__
import collections
# 查看属性:__doc__:查看collections文档介绍信息
print(collections.__doc__)
>>>
This module implements specialized container datatypes providing
alternatives to Python's general purpose built-in containers, dict,
list, set, and tuple.
* namedtuple factory function for creating tuple subclasses with named fields
* deque list-like container with fast appends and pops on either end
* ChainMap dict-like class for creating a single view of multiple mappings
* Counter dict subclass for counting hashable objects
* OrderedDict dict subclass that remembers the order entries were added
* defaultdict dict subclass that calls a factory function to supply missing values
* UserDict wrapper around dictionary objects for easier dict subclassing
* UserList wrapper around list objects for easier list subclassing
* UserString wrapper around string objects for easier string subclassing
3、查看collections的所有可用的类、方法和属性:dir(collections)
# 使用函数dir():查看collections的所有可用的类、方法和属性
print(dir(collections))
>>>
['ChainMap', 'Counter', 'OrderedDict', 'UserDict', 'UserList', 'UserString', '_Link',
'_OrderedDictItemsView', '_OrderedDictKeysView', '_OrderedDictValuesView', '__all__',
'__builtins__', '__cached__', '__doc__', '__file__', '__getattr__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '_chain', '_collections_abc',
'_count_elements', '_eq', '_heapq', '_iskeyword', '_itemgetter', '_nt_itemgetters',
'_proxy', '_recursive_repr', '_repeat', '_starmap', '_sys', 'abc', 'defaultdict',
'deque', 'namedtuple']
4、查看collections模块下的某个函数或方法有哪些属性
。例如:dir(namedtuple)
# 使用函数dir():查看一下namedtuple有哪些属性
print(dir(namedtuple))
>>>
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
5、查看collections模块下的某个函数或方法的官方文档
。例如:namedtuple.__doc__
print(namedtuple.__doc__)
>>>
Returns a new subclass of tuple with named fields.
>>> Point = namedtuple('Point', ['x', 'y'])
>>> Point.__doc__ # docstring for the new class
'Point(x, y)'
>>> p = Point(11, y=22) # instantiate with positional args or keywords
>>> p[0] + p[1] # indexable like a plain tuple
33
>>> x, y = p # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessible by name
33
>>> d = p._asdict() # convert to a dictionary
>>> d['x']
11
>>> Point(**d) # convert from a dictionary
Point(x=11, y=22)
>>> p._replace(x=100) # _replace() is like str.replace() but targets named fields
Point(x=100, y=22)
6、查看collections模块下的某个函数或方法的帮助文档
。例如:help(collections.deque)
print(help(collections.deque))
>>>
Help on class deque in module collections:
class deque(builtins.object)
| deque([iterable[, maxlen]]) --> deque object
|
| A list-like sequence optimized for data accesses near its endpoints.
|
| Methods defined here:
|
| __add__(self, value, /)
| Return self+value.
|
| __bool__(self, /)
| self != 0
|
| __contains__(self, key, /)
| Return key in self.
|
| __copy__(...)
| Return a shallow copy of a deque.
|
| __delitem__(self, key, /)
| Delete self[key].
|
| __eq__(self, value, /)
| Return self==value.
|
| __ge__(self, value, /)
| Return self>=value.
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __getitem__(self, key, /)
| Return self[key].
|
| __gt__(self, value, /)
| Return self>value.
|
| __iadd__(self, value, /)
| Implement self+=value.
|
| __imul__(self, value, /)
| Implement self*=value.
|
| __init__(self, /, *args, **kwargs)
| Initialize self. See help(type(self)) for accurate signature.
|
| __iter__(self, /)
| Implement iter(self).
|
| __le__(self, value, /)
| Return self<=value.
|
| __len__(self, /)
| Return len(self).
|
| __lt__(self, value, /)
| Return self<value.
|
| __mul__(self, value, /)
| Return self*value.
|
| __ne__(self, value, /)
| Return self!=value.
|
| __reduce__(...)
| Return state information for pickling.
|
| __repr__(self, /)
| Return repr(self).
|
| __reversed__(...)
| D.__reversed__() -- return a reverse iterator over the deque
|
| __rmul__(self, value, /)
| Return value*self.
|
| __setitem__(self, key, value, /)
| Set self[key] to value.
|
| __sizeof__(...)
| D.__sizeof__() -- size of D in memory, in bytes
|
| append(...)
| Add an element to the right side of the deque.
|
| appendleft(...)
| Add an element to the left side of the deque.
|
| clear(...)
| Remove all elements from the deque.
|
| copy(...)
| Return a shallow copy of a deque.
|
| count(...)
| D.count(value) -> integer -- return number of occurrences of value
|
| extend(...)
| Extend the right side of the deque with elements from the iterable
|
| extendleft(...)
| Extend the left side of the deque with elements from the iterable
|
| index(...)
| D.index(value, [start, [stop]]) -> integer -- return first index of value.
| Raises ValueError if the value is not present.
|
| insert(...)
| D.insert(index, object) -- insert object before index
|
| pop(...)
| Remove and return the rightmost element.
|
| popleft(...)
| Remove and return the leftmost element.
|
| remove(...)
| D.remove(value) -- remove first occurrence of value.
|
| reverse(...)
| D.reverse() -- reverse *IN PLACE*
|
| rotate(...)
| Rotate the deque n steps to the right (default n=1). If n is negative, rotates left.
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| maxlen
| maximum size of a deque or None if unbounded
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| __hash__ = None
01. namedtuple函数——定义一个返回值为tuple的类
(1)namedtuple 功能详解: namedtuple() 定义一个返回值为tuple的类。
(2)namedtuple语法说明: namedtuple('名称', [ 属性list])
(3)namedtuple定义的tuple类的元素访问方式: namedtuple()规定了元组的元素个数,访问类中元素的方式有两类:
- 使用【下标】获取元素;
- 使用【属性】直接获取元素。
from collections import namedtuple
User = namedtuple("Student", ["name", "age", "weight"]) # 定义类名(Student)和类的格式(包含属性:"name", "age", "weight")
user = User("admin", "20", "60") # 实例化类
# 多变量赋值
name, age, weight = user
print(User)# 类的形式
>>>
__main__.Student
print(user) # 实例化后的类
>>>
Student(name='admin', age='20', weight='60')
# 通过类实例的下标访问类的各个元素
print(user[0])
>>>
'admin'
print(name, age, weight)
>>>
admin 20 60
# 通过类实例的属性访问类的各个元素
print(user.name, user.age, user.weight)
>>>
admin 20 60
我们知道,Python中元组的一个重要特征就是元素不可增删改,而查找tuple元素时一般采取索引
。
使用namedtuple(typename, field_name)
可以命名tuple中的元素
,之后便可使用名字来查找tuple中的值,有点类似于字典中的查找。
from collections import namedtuple
animal = namedtuple('animal', 'name age') # 等价于User = namedtuple("Student", ["name", "age", "weight"]),即:定义类名(Student)和类的格式
mark = animal(name='dog', age=2)
print(mark)
>>>
animal(name='dog', age=2)
namedtuple() 相当于直接定义了一个新的类,但是这个类跟传统定义 class 的方式又有着巨大区别。
- 该方式会比直接定义 class 的方式省很多空间;
- 该方式的返回值是一个 tuple,支持 tuple 的各种操作。
同时,namedtuple() 还自带两个非常好用的方法。
- User._make(user) :将序列直接转换为新的 tuple 对象。
- user._asdict():将tuple转化为dict对象。
# 将序列直接转换为新的 tuple 对象
user = ["root", 32, 65]
user = User._make(user)
print(user)
>>>
Student(name='root', age=32, weight=65)
# 将tuple转化为dict对象
user = User("admin", 20, 60)
print(user._asdict())
>>>
OrderedDict([('name', 'admin'), ('age', 20), ('weight', 60)])
(1)生成list-tuple型的复合的list
user =User("root", 32, 65)
user1 = User('admin', 20, 60)
cumsum_list = list()
cumsum_list.append(user1) # 等价于cumsum_list.append(tuple(user1))
cumsum_list.append(user)
cumsum_list
>>>
[Student(name='root', age=32, weight=65),
Student(name='root', age=32, weight=65)]
# cumsum_list外层支持list的所有操作,内层为tuple,支持tuple的所有操作
cumsum_list[0].name # 通过属性访问元素
>>>
'root'
cumsum_list[0][0] # 通过下标访问元素
>>>
'root'
(2)生成list-dict型的复合的list
user1 = User("root", 32, 65)
user2 = User("admin", 30, 60)
cumsum_list = list()
cumsum_list.append(user1._asdict()) # 等价于cumsum_list.append(dict(user1._asdict()))
cumsum_list.append(user2._asdict())
cumsum_list
>>>
[OrderedDict([('name', 'root'), ('age', 32), ('weight', 65)]),
OrderedDict([('name', 'admin'), ('age', 30), ('weight', 60)])]
# cumsum_list支持list的所有操作,内层为dict,支持dict的所有操作
cumsum_list[0]['name']
>>>
'root'
完整应用实例:
# 定义一个圆,可通过元组对应的名字来访问圆的圆心坐标、半径。
from collections import namedtuple
circle = namedtuple("Circle", ["x", "y", "r"])
print(circle)
>>>
<class '__main__.Circle'>
# 实例化一个返回值为tuple的类
circle1 = circle(2,4,6) # 圆心(2,4),半径6
print("实例化的圆:", circle1)
>>>
实例化的圆: Circle(x=2, y=4, r=6)
# 通过属性访问各元素值
print("circle1的圆心:",circle1.x, circle1.y)
print("circle1的半径:",circle1.r)
>>>
circle1的圆心: 2 4
circle1的半径: 6
propotion = circle1[2]*circle1[2]*3.14
print("圆的面积为:", propotion)
>>>
圆的面积为: 113.04
对于从csv或sqlite3模块返回的结果,使用_make方法
将它们分配给命令数组非常有用。
Student = namedtuple('Student', 'id, name, age, className, score')
import csv
"""
csv.reader()返回一个reader对象,利用该对象遍历csv文件中的行。 从csv文件中读取的每一行都作为字符串列表返回。
"""
for emp in map(Student._make, csv.reader(open("students.csv", "rb"))):
print(emp.name, emp.age)
import sqlite3
conn = sqlite3.connect('/studentdata')
cursor = conn.cursor()
cursor.execute('SELECT id, name, age, className, score FROM students')
for emp in map(Student._make, cursor.fetchall()):
print(emp.name, emp.age)
02. ChainMap ——将多个字典集合到一个字典,并对外提供一个统一视图
ChainMap功能详解: ChainMap() 将多个字典集合到一个字典,并对外提供一个统一视图。
注意:该操作并是不将所有字典做了一次拷贝,实际上是在多个字典的上层又进行了一次封装而已。
from collections import ChainMap
user1 = {"name":'admin', "age":20}
user2 = {"name":'root', "weight":65}
users = ChainMap(user1, user2)
print(users.maps)
>>>
[{'name': 'admin', 'age': 20}, {'name': 'root', 'weight': 65}]
# 修改【统一视图字典】中的某个元素,类似字典key-value的访问方式
users.maps[0]["name"] = "tiger"
print(users.maps)
>>>
[{'name': 'tiger', 'age': 20}, {'name': 'root', 'weight': 65}]
# 循环遍历查看【统一视图字典】的各个元素,如果 ChainMap() 中的多个字典有重复 key,查看的时候可以看到所有的 key,但遍历的时候却只会遍历 key 第一次出现的位置,其余的忽略。
for key, value in users.items():
print(key, value)
>>>
name tiger
weight 65
age 20
如果 ChainMap() 得到的【统一视图字典】中的多个字典有重复 key时,
- 通过
users.maps
查看的时候,可以看到所有的 key; - 通过
for key, value in users.items():
遍历的时候,却只会遍历 key 第一次出现的位置,其余的忽略。
同时,我们 可以通过返回的新的【统一视图字典】来更新
【原来的字典】数据。进一步验证了该操作不是做的拷贝,而是直接指向原字典。
03. deque——在list两端快速【添加】或【弹出】指定元素
(1)deque功能详解: dqueue 是 ”double-ended queue” 的简称,是一种类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)操作,大大加快了遍历速度。
- deque([list])
.append
(元素):在list的右侧添加指定元素; - deque([list])
.appendleft
(元素):在list的左侧添加指定元素; - deque([list])
.popleft()
:弹出list最左侧的元素; - deque([list])
.pop()
:弹出list最右侧的元素; - deque([list])
.extendleft
(元素):在list的左侧添加指定元素; - deque([list])
.extend
(元素):在list的右侧添加指定元素; deque([list]).reverse()
:反转队列;deque([list]).count(元素)
:统计某元素出现的次数;deque([list]).cleart()
:清空队列;deque([list]).index(元素)
:取得元素下标;deque([list]).insert(位置,元素)
:指定位置插入元素;deque([list]).maxlen
:只读的属性,deque的最大长度,如果无解,就返回None;
Python中的
list
是基于数组实现的,所以,查找容易,但是插入和删除操作时间复杂度较大
。
deque就是为了高效实现插入和删除操作的双向列表
,适合用于队列和栈,而且线程安全。
- list只提供了append和pop方法来从list的尾部插入或者删除元素;
- deque新增了appendleft/popleft等方法可以更高效的在元素的开头来插入/删除元素。
(2)deque语法说明: deque(列表)
, 返回值:列表
(3)deque典型范例:
from collections import deque
q = deque([1,2,3])
q.append('4') # 在list的右侧添加元素’4‘
q.appendleft('0') # 在list的左侧添加元素’0‘
print(q)
>>>
deque(['0', 1, 2, 3, '4'])
print(q.popleft()) # 弹出list最左侧的元素;
>>>
0
print(q)
>>>
deque([1, 2, 3, '4'])
print(q.pop()) # 弹出list最右侧的元素;
>>>
4
print(q)
>>>
deque([1, 2, 3]) # 生成的deque([1, 2, 3])类型为list,支持list的所有操作
from collections import deque
d = deque([1,2,3,4,5])
d.extendleft([0])
print(d)
>>>
deque([0, 1, 2, 3, 4, 5])
# reverse()反转队列
d.reverse()
print(d)
>>>
deque([5, 4, 3, 2, 1, 0])
# count()计数
print(d.count(1)) # 有该元素则返回对应的统计次数
>>>
1
print(d.count('R')) # 无该元素则返回0
>>>
0
# clear()清空队列
d.clear()
print(d)
>>>
deque([7, 6, 5, 4, 3, 2, 1])
# index()取得元素下标
d = deque(['a','b','c','d','e'])
print(d.index('c'))
>>>
2
# insert()指定位置插入元素
d.insert(1,'Runsen')
print(d)
>>>
deque(['a', 'Runsen', 'b', 'c', 'd', 'e'])
04. Counter——统计每个元素出现的次数
(1)Counter功能详解: Counter 可以简单理解为一个计数器,可以统计每个元素出现的次数。同样地, Counter() 需要接受一个可迭代的对象
(如:list)。
(2)Counter语法说明 collections.Counter()
,返回值:可迭代内容的字典的Counter类。
- Counter对象创建的四种方法:
c = Counter() # 创建一个空的Counter类
c = Counter('gallahad') # 从一个可iterable对象(list、tuple、dict、字符串等)创建——字符串型
c = Counter(["cat", "dog", "cat", "bird", "horse", "cat"]) # 从一个可iterable对象(list、tuple、dict、字符串等)创建——list型
c = Counter({'a': 4, 'b': 2}) # 从一个字典对象创建
c = Counter(a=4, b=2) # 从一组键值对创建
(3)Counter返回值中元素的访问方式: Counter的返回值是一个字典,通过调用most_common()
方法,可以求得 Top k 问题
,返回值为list-tuple的形式
,外层与list的调用方式相同,内层与tuple的调用方式相同。
counter.most_common(N)
将Counter按照value从大到小排列,获取前N个元素。counter.elements()
取得计数器中的所有元素。sorted(counter)
将Counter中的key进行排序,返回的是所有key的列表。''.join(counter.elements())
将Counter转换成字符串。counter.update(collections.Counter('a'))
更新计数器,其实在原本的counter基础上更新计数器,如果原来没有该key,则新建key,如果有该key则,在该key的value基础上加1。counter.subtract('abdabcabcg')
相减计数器的values,即原来的计数器中的每一个元素的数量减去后添加的元素的数量。sum(c.values())
:统计所有的数目;list(c)
:列出所有唯一的元素;set(c)
:转换为set;dict(c)
:转换为常规的dict;c.items()
:转换为(elem,cnt)对构成的列表;c.most_common()[:-4:-1]
:输出n个数目最小元素;c += Counter()
:删除数目为0和为负的元素;Counter(dict(c.items()))
:从(elem,cnt)对构成的列表转换为counter;c.clear()
:清空counter;c.total()
:计算总计数值。
对Counter对象进行数学操作,得到多集合(counter中元素数目大于0)
加法和减法操作,是相加或者相减对应元素的数目
;交集和并集返回对应数目的最小值和最大值
;
每个操作均接受的是所有有符号的数目,但是输出并不包含数目为0或者为负的元素;
# Counter用来统计各个值出现的次数——【字符串序列】
from collections import Counter
c = Counter('abcdeabcdabcaba')
print(c)
>>>
Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})
b = dict(c)
print(b)
>>>
{'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1}
print(b['name'])
>>>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'name'
print(c['name'])
>>>
0
# elements()取得计数器中的所有元素。
print(counter.elements())
# 输出如下
<itertools.chain object at 0x0000025B1477BF98>
print(list(c.elements())) # 需要用list转化为可读的list元素集列表
>>>
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']
# update()更新计数器
g = collections.Counter('agd')
print(g)
>>>
Counter({'a': 1, 'g': 1, 'd': 1})
c.update(g)
print(c)
>>>
Counter({'a': 6, 'b': 4, 'c': 3, 'd': 3, 'e': 1, 'g': 1})
# subtract()相减计数器的values,即原来的计数器中的每一个元素的数量减去后添加的元素的数量
c.subtract('abdda')
print(c)
>>>
Counter({'a': 4, 'b': 3, 'c': 3, 'd': 1, 'e': 1, 'g': 1})
# Counter用来统计各个值出现的次数——【字符串list】
from collections import Counter
animals = ["cat", "dog", "cat", "bird", "horse", "tiger", "horse", "cat"]
animals_counter = Counter(animals)
print(animals_counter)
>>>
Counter({'cat': 3, 'horse': 2, 'dog': 1, 'bird': 1, 'tiger': 1})
print(animals_counter.most_common(2))
>>>
[('cat', 3), ('horse', 2)]
或者
from collections import Counter
test_counter_data = ["cat", "dog", "cat", "bird", "horse", "tiger", "horse", "cat"]
counter_data = Counter()
for item in test_counter_data:
counter_data[item] += 1
print(counter_data)
>>>
Counter({'cat': 3, 'horse': 2, 'dog': 1, 'bird': 1, 'tiger': 1})
等价于
counter_data = Counter(test_counter_data)
print(counter_data)
>>>
Counter({'cat': 3, 'horse': 2, 'dog': 1, 'bird': 1, 'tiger': 1})
如何实现按照词频顺序对单词进行排序
?
from collections import Counter
test_counter_data = ["cat", "dog", "cat", "bird", "horse", "tiger", "horse", "cat"]
counter_data = Counter(test_counter_data)
print(counter_data)
# 按照词频顺序对单词进行排序
import operator
sorted_word_to_cnt = sorted(counter_data.items(),key = operator.itemgetter(1),reverse = True)
print(sorted_word_to_cnt)
上述示例说明:Counter(test_counter_data_list)
等价于
for item in test_counter_data_list:
counter_data[item] += 1
因此,代码段大大缩减。
完整范例:
c = Counter(a=4,b=2,c=0,d=-2)
print(c)
>>>
Counter({'a': 4, 'b': 2, 'c': 0, 'd': -2})
sum(c.values())# 统计所有的数目
>>>
4
list(c)# 列出所有唯一的元素
>>>
['a', 'b', 'c', 'd']
set(c)# 转换为set
>>>
{'a', 'b', 'c', 'd'}
dict(c)# 转换为常规的dict
>>>
{'a': 4, 'b': 2, 'c': 0, 'd': -2}
c.items()# 转换为(elem,cnt)对构成的列表
>>>
dict_items([('a', 4), ('b', 2), ('c', 0), ('d', -2)])
c.most_common()[:-4:-1]# 输出n个数目最小元素
>>>
[('d', -2), ('c', 0), ('b', 2)]
c += Counter()# 删除数目为0和为负的元素
print(c)
>>>
Counter({'a': 4, 'b': 2})
Counter(dict(c.items()))# 从(elem,cnt)对构成的列表转换为counter
>>>
Counter({'a': 4, 'b': 2})
c.clear()# 清空counter
print(c)
>>>
Counter()
# Counter对象进行数学操作
c = Counter(a=3,b=1,c=-2)
print(c)
>>>
Counter({'a': 3, 'b': 1, 'c': -2})
d = Counter(a=1,b=2,c=4)
print(d)
>>>
Counter({'c': 4, 'b': 2, 'a': 1})
"""在Counter对象进行数学操作,得多集合(counter中元素数目大于0)加法和减法操作,是相加或者相减对应元素的数目;
交集和并集返回对应数目的最小值和最大值;
每个操作均接受的是有符号的数目,但是输出并不包含数目为0或者为负的元素;"""
c+d#求和
>>>
Counter({'a': 4, 'b': 3, 'c': 2})
c-d#求差
>>>
Counter({'a': 2})
c & d#求交集
>>>
Counter({'a': 1, 'b': 1})
c | d#求并集
>>>
Counter({'a': 3, 'b': 2, 'c': 4})
05. OrderedDict——保证了元素的插入顺序
(1)OrderedDict 功能详解: OrderedDict 是字典的子类,保证了元素的插入顺序。
(1)在Python3.6之前的字典是无序的,但是有时候我们需要保持字典的有序性,orderDict可以在dict的基础上实现字典的有序性,这里的有序指的是按照字典key插入的顺序来排列,这样就实现了一个先进先出的dict,当容量超出限制时,先删除最早添加的key。
(2)在Python3.7 版本下,字典同样也保证了元素的插入顺序。那相比内置字典 OrderedDict 有哪些升级呢。
- 算法上,
OrderedDict 可以比 dict 更好地处理频繁的重新排序操作
。在跟踪最近的访问这种场景(例如在 LRU cache)下非常适用。 - OrderedDict 类有一个
move_to_end() 方法
,可以有效地将元素移动到任一端。
(2)OrderedDict 常见属性:
dic.keys()
:获得字典的所有键 ;dic.values()
:获得字典的所有值;dic.items()
:以列表返回可遍历的(键, 值) 元组数组;dic.pop(键)
:删除指定的键值;dic.popitem()方法
,默认删除字典最后一个元素;dic.update({'k1':'v1111','k10':'v10'})
:更新字典;dict.move_to_end(键)
:将元素移动到末尾;
from collections import OrderedDict
user = OrderedDict()
user["name"] = "admin"
user["age"] = 23
user["weight"] = 65
print(user)
>>>
OrderedDict([('name', 'admin'), ('age', 23), ('weight', 65)])
user.move_to_end("name") # 将元素移动到末尾
print(user)
>>>
OrderedDict([('age', 23), ('weight', 65), ('name', 'admin')])
# 字典所有的键
user.keys()
>>>
odict_keys(['name', 'age', 'weight'])
# 字典所有值
print(user.values())
>>>
odict_values(['admin', 23, 65])
# items() 方法以列表返回可遍历的(键, 值) 元组数组
print(dic.items())
>>>
odict_items([('name', 'admin'), ('age', 23), ('weight', 65)])
#pop()方法,删除指定的键值
user.pop('name')
print(user)
>>>
OrderedDict([('age', 23), ('weight', 65)])
#popitem()方法,默认删除字典最后一个元素
user.popitem()
print(user)
>>>
OrderedDict([('age', 23)])
# update()更新字典
user.update({'k1':'v1111','k10':'v10'})
print(user)
>>>
OrderedDict([('age', 23), ('k1', 'v1111'), ('k10', 'v10')])
user.move_to_end("name", last=False) # 将元素移动到开头
print(user)
>>>
OrderedDict([('name', 'admin'), ('age', 23), ('weight', 65)])
原始的字典定义和通过OrderedDict()定义字典的用法区别的示例:
original_dict = {'a':2, 'b':4, 'c':5}
for key, value in original_dict.items():
print(key,value)
>>>
a 2
b 4
c 5
# OrderedDict是按照字典创建时的插入顺序来排序的。
original_dict = OrderedDict([('a',2), ('b',4), ('c',5)])
for key, value in original_dict.items():
print(key, value)
>>>
a 2
b 4
c 5
06. defaultdict——内置 dict 类的子类,实现了当 key 不存在时返回默认值的功能
(1)defaultdict 功能详解: defaultdict 是内置 dict 类的子类,它实现了当 key 不存在时返回默认值的功能,除此之外,与内置 dict 功能完全一样。
(2)defaultdict 语法说明: collections.defaultdict(函数)
,返回值:返回括号里的函数。
(3)defaultdict 典型范例:
"""
这个类似于我们使用:try...except...这个关键字的用法
"""
d1 = {"one":1,"two":2,"three":3}
print(d1["four"])
>>>
KeyError: 'four'
#上面的会报错,下面的就会返回函数,告诉我们错了
func = lambda:"错了"
d2 = collections.defaultdict(func)
d2['one']=1
d2['two']=2
print(d2['four'])
>>>
错了
from collections import defaultdict
default_dict = defaultdict(int)
default_dict['x'] = 10
print(default_dict['x'])
>>>
10
print(default_dict['y'])
>>>
0
给 defaultdict 传了一个自定义函数,实现当字典中不存在所取 key 时返回默认的用户信息。
def getUserInfo():
return{
"name":'默认name',
"age":0,
}
default_dict = defaultdict(getUserInfo)
admin = default_dict["admin"] # 访问dict不存在的key="admin"时,返回默认值
print(admin)
>>>
{'name': '默认name', 'age': 0}
# 通过键值对访问,修改指定key的value
admin["age"] = 34
print(admin)
>>>
{'name': '默认name', 'age': 34}
- defaultdict(list) :定义defaultdict字典的
value值的type为list类型
- defaultdict(int) :定义defaultdict字典的
value值的type为int类型
from collections import defaultdict
test_data = (('cat',2),('dog',5),('sheep',3),('cat',1),('sheep',6))
print(type(test_data))
>>>
<class 'tuple'>
test_data_dict = defaultdict(list) # 定义defaultdict字典的value值的type为list类型
print(test_data_dict)
>>>
defaultdict(<class 'list'>, {})
for name, num in test_data:
test_data_dict[name].append(num)
print(test_data_dict)
>>>
defaultdict(<class 'list'>, {'cat': [2, 1], 'dog': [5], 'sheep': [3, 6]})
# defaultdict为一个dict-list的复合型,外层访问与dict一致,内层访问与list一致。
print(test_data_dict['cat'])
>>>
[2, 1]
参考链接: