劝学
颜真卿〔唐代〕
三更灯火五更鸡,正是男儿读书时。
黑发不知勤学早,白首方悔读书迟。
collections是python内置的模块,提供常用的方法有namedtuple,defaultdict,deque,Counter,OrderedDict,ChainMap。
1. namedtuple
1.1 tuple
在学些namedtuple先来看看python的tuple。
- tuple是不可变的,可迭代的
- 支持拆包
name_tuple = ('kevin', 'man', 18)
name, gender, age = name_tuple
print(name, gender, age)
name, *other = name_tuple
print(name, other, type(other))
# 结果
# kevin man 18
# kevin ['man', 18] <class 'list'>
- tuple不可变性不是绝对的;
name_tuple = ('kevin', [18, 19])
name_tuple[1].append(20)
print(name_tuple)
# 结果
# ('kevin', [18, 19, 20])
tuple比list好的地方:immutable(不可变)的重要性,
- 性能优化(指出元素全部为immutable的tuple会作为常量的编译时确定,因此产生了如此显著的速度差异)
- 线程安全
- 可以作为dict的key
- 拆包特性
1.2 namedtuple
- namedtuple函数所创建(返回)的是一个 元组的子类
- namedtuple函数所创建元组,中文名称为 具名元组
namedtuple和tuple创建元组的区别
- 使用namedtuple,我们既可以使用index来访问,也可以使用具名元组中每个字段的名称来访问;在使用普通元组的时候,我们只能通过index来访问元组中的某个数据
- namedtuple省空间,内存效率高(数据处理)
User = namedtuple("User", ['name', 'age', 'height', 'edu'])
# 1.直接构造User对象,不需要完整的参数
# 传入tuple
user_tuple = ('kevin', 18, 175)
user = User(*user_tuple, 'master')
# 传入dict
user_dict = {
'name': 'kevin',
'age': 18,
'height': 175
}
user = User(**user_dict, edu='master')
# 2.使用_make方法构建
# 需要完整的参数,传入的参数是iterable(list,dict都可以)
User._make(user_tuple)
# 拆包
name, age, *other = user
print(name, age, other)
# 转化为OrderDict
user_info_dict = user._asdict()
2. defaultdict
defaultdict是实现的 dict 的一个子类,一般的dict会导致KeyError异常,而defaultdict可以避免KeyError异常。
user_dict = {}
user_list = ['kevin1', 'kevin2', 'kevin1', 'kevin2', 'kevin1', 'kevin2', 'kevin3']
# 版本一:
for user in user_list:
if user not in user_dict:
user_dict[user] = 1
else:
user_dict[user] += 1
# 版本二:比版本一更佳高效
for user in user_list:
user_dict.setdefault(user, 0)
user_dict[user] += 1
# 版本三:代码最少,最不容易出错
user_default_dict = defaultdict(int)
for user in user_list:
user_default_dict[user] += 1
当想初始化更复杂的数据的时候,可以定义函数返回值
def generate_dict():
return {
'name': 'kevin',
'age': 18
}
test_dict = defaultdict(generate_dict)
print(test_dict['kevin'])
print(test_dict)
# 结果
# {'name': 'kevin', 'age': 18}
# defaultdict(<function generate_dict at 0x109223560>, {'kevin': {'name': 'kevin', 'age': 18}})
3. deque
deque模块提供了两端都可以操作的序列,在序列的前后都可以执行添加或删除操作。deque GIL线程安全的,list不是安全线程的。底层是c语言写的,性能好。
常用的方法:
# 1.appendleft()
user_list = deque(['kevin', 'kevin1', 'kevin2'])
user_list.appendleft('kevin3')
print(user_list)
# 结果
# deque(['kevin3', 'kevin', 'kevin1', 'kevin2'])
# 2.copy() 此处为浅拷贝
user_list1 = deque(['kevin', ['kevin1', 'kevin2', 'kevin3'], 'kevin2'])
user_list2 = user_list1.copy()
user_list1.append('kevin3')
print(id(user_list1), id(user_list2))
print(user_list1, user_list2)
# 结果
# 4391470368 4392448640
# deque(['kevin', ['kevin1', 'kevin2', 'kevin3'], 'kevin2', 'kevin3']) deque(['kevin', ['kevin1', 'kevin2', 'kevin3'], 'kevin2'])
user_list1[1].append('kevin4')
print(user_list1, user_list2)
# 结果,修改原数据第二个元素列表中的值,两个deque对象都改变
# deque(['kevin', ['kevin1', 'kevin2', 'kevin3', 'kevin4'], 'kevin2', 'kevin3']) deque(['kevin', ['kevin1', 'kevin2', 'kevin3', 'kevin4'], 'kevin2'])
# 3.extend() 返回值为None,直接在user_list叠加
user_list.extend(user_list1)
print(user_list)
# 结果
# deque(['kevin3', 'kevin', 'kevin1', 'kevin2', 'kevin', ['kevin1', 'kevin2', 'kevin3', 'kevin4'], 'kevin2', 'kevin3'])
4. Counter
Counter 是实现的 dict 的一个子类,可以用来方便地计数。
from collections import Counter
user_list = ['kevin1', 'kevin2', 'kevin1', 'kevin2', 'kevin1', 'kevin2', 'kevin3']
user_counter = Counter(user_list)
print(user_counter)
# 结果
# Counter({'kevin1': 3, 'kevin2': 3, 'kevin3': 1})
常用的使用方法
# 1.update()
count1 = Counter('wleflwjflsjgl')
count2 = Counter('jljlfsjlgsjlglsgjgls')
count1.update(count2)
print(count1)
# 结果
# Counter({'l': 10, 'j': 7, 's': 5, 'g': 5, 'f': 3, 'w': 2, 'e': 1})
# 2.most_common() top n的问题
top2 = count1.most_common(2)
print(top2)
top3 = count1.most_common(3)
print(top3)
# 结果
# [('l', 10), ('j', 7)]
# [('l', 10), ('j', 7), ('s', 5)]
5. OrderedDict
很多人认为python中的字典是无序的,其实python3中dict是有序的,在python2中dict是无序的。OrderedDict继承dict,dict有的方法,OrderedDict也能用。OrderedDict实现了对字典对象中元素的排序。请看下面示例:
from collections import OrderedDict
order_dict = OrderedDict()
order_dict['b'] = 'kevin2'
order_dict['c'] = 'kevin3'
order_dict['a'] = 'kevin1'
print(order_dict)
# 结果
# OrderedDict([('b', 'kevin2'), ('c', 'kevin3'), ('a', 'kevin1')])
常用的方法
# 1.popitem() 弹出最后一个键值对,并把原字典的最后一个元素删除
print(order_dict.popitem())
print(order_dict)
# 结果
# ('a', 'kevin1')
# OrderedDict([('b', 'kevin2'), ('c', 'kevin3')])
# 2.pop() 删除指定key,弹出value
print(order_dict.pop('a'))
print(order_dict)
# 结果
# kevin1
# OrderedDict([('b', 'kevin2'), ('c', 'kevin3')])
# 3.move_to_end(key) 根据传入的key,把这一键值对移动到最后
order_dict.move_to_end('c')
print(order_dict)
# 结果
# OrderedDict([('b', 'kevin2'), ('a', 'kevin1'), ('c', 'kevin3')])
6. ChainMap
ChainMap类用于快速链接多个字典(Dict),以便将它们视为一个单元。它通常比创建新字典和多次调用update()快得多。
from collections import ChainMap
user_dict1 = {'a': 'kevin1', 'b': 'kevin2'}
user_dict2 = {'c': 'kevin2', 'd': 'kevin4'}
new_dict = ChainMap(user_dict1, user_dict2)
for k, v in new_dict.items():
print(k, v)
# 结果
# c kevin2
# d kevin4
# a kevin1
# b kevin2
如果多个字典有相同的key,使用ChainMap的时候只会取第一次。请看如下示例:
from collections import ChainMap
user_dict1 = {'a': 'kevin1', 'b': 'kevin2'}
user_dict2 = {'b': 'kevin2', 'd': 'kevin4'}
# 如果有相同的key,遍历只取一次
new_dict = ChainMap(user_dict1, user_dict2)
for k, v in new_dict.items():
print(k, v)
# 结果
# b kevin2
# d kevin4
# a kevin1
修改ChainMap中的某个值
print(new_dict)
new_dict.maps[0]['b'] = 'kevin'
print(new_dict)
# 结果
# ChainMap({'a': 'kevin1', 'b': 'kevin2'}, {'c': 'kevin2', 'd': 'kevin4'})
# ChainMap({'a': 'kevin1', 'b': 'kevin'}, {'c': 'kevin2', 'd': 'kevin4'})
user = User(*user_tuple, 'master')
User._make(user_tuple)Î
网友评论