在介绍collections之前,大都知道python中已经有一些数据类型,诸如list,tuple,dict这类型,而collections可以理解对上述类型的一个扩展。下面介绍一下collections中常用到的几种数据类型
1.namedtuple()
python中的tuple是可迭代的,可哈希的,但是不可修改
name_list = ("python","java","php")
for name in name_list:
print(name)
name_dict = {}
name_dict[name_list]="result"
print(name_dict)
# 元组的拆包功能
name_list = ("小明",29,175)
name,age,height = name_list
name ,*other = name_list
print(other)
回归了tuple之后,我们介绍一下namedtuple的功能
描述一个人的特点的时候,我们会使用姓名,年龄,身高这些属性attribute去描述,自然的会创建一个类,如下
class Person():
def __init__(self,name,age,height):
self.name = name
self.age = age
self.height = height
但如果只是为了创建一个包含某些属性的数据机构的时候,使用上面的类的创建方式会非常浪费空间内存,而且代码较为繁琐,此时就可以使用collections中的namedtuple创建一个类,因此如果是创建一些简单的对象的时候就可以使用namedtuple
from collections import namedtuple
Person = namedtuple("Person",["name","age","height"])
user = Person(name = "jack",age=29,height=175)
print(user.name,user.age,user.height)
# 函数变量参数
user_tuple = ("rose",28,165)
user2 = Person(*user_tuple)
#
user_dict ={
"name":"rose2",
"age":15,
"height":160
}
user3 = Person(**user_dict)
#使用namedtuple中自带的_make函数,传入一个可迭代对象,包括list,dict,tuple
user4 = Person._make(user_tuple)
#既然是对象的属性值,肯定是可以表示成字典的形式,因此如果需要将其表示为字典
user_info_dict = user._asdict()
2.defaultdict
常见一种统计个数的功能,str.count() 方法用于统计字符串里某个字符出现的次数,那如果是list结构中的想统计个数,可能会以如下的形式进行统计,比如统计每个成绩段的个数
grade = ["a","a","b","c"]
grade_dict = {}
for index in grade:
if index not in grade_dict:
grade_dict[index] = 1
else:
grade_dict[index] += 1
print(grade_dict)
#这个时候可以做如上优化
grade = ["a","a","b","c"]
grade_dict = {}
for index in grade:
user_dict.setdefault(index,0)
user_dict[index] += 1
但是一般我们可能想不到使用setdefault这个功能,这个时候就需要defaultdic这个功能了,我们知道在Python3中如果在字典中索引一个不存在的key会报错提示key-value的错误,因此使用defaultdict[key]的时候就不会报key-value的错误了
from collections import defaultdict
grade = ["a","a","b","c"]
grade_dict = defaultdict(int)
for index in grade:
grade_dict[index] += 1
print(grade_dict)
这个最大的用处就是我们函数中经常出现判断如果传入了参数,就是用传入的参数,没有传入使用默认参数的形式,如下
def function(newDic = {}):
# 使用sql查询一个比如某个信息info值,如果传入了info则使用传入的值,否则使用查询的值
""""""
temp = defaultdict(dict)
temp.update(newDic)
newDic = temp
print(info if not newDic['info'] else newDic['info'])
另一种用法就是,比如在传入参数的时候,如果传入了属性,则使用传入的属性值,如果没有传入则使用默认值和上述的参数传递大同小异
def generate_dict():
return {
"name":"",
"age":0
}
default_dict = defaultdict(generate_dict)
default_dict['xiaoming']
print(default_dict)
3.deque
queue是Python3的队列,常用以下方式进行引入
from queue import Queue
双端队列deque顾名思义就是可以在队列两边进行操作的队列,比如append,leftappend,使用之前导入对应的包
from collections import deque
具体的有哪些函数可以调用,可以导入包之后进行查看,因为可调用的函数较多,这里不再一一介绍,这里想介绍的是在队列(或者双端队列,或者列表)中,常用的一种拷贝方式,深拷贝与浅拷贝
先来看一下浅拷贝
import copy
from collections import deque
user_deque = (["boy1","boy2","boy3"])
#浅拷贝
user_deque2 = user_deque.copy()
#浅拷贝,如果对应的元素是不可变元素,如tuple中的元素,则复制该元素,如果是可变的元素,如list,就会直接指向该元素
user_deque2[1]="boy5"
print(id(user_deque),id(user_deque2))
print(user_deque,user_deque2)
#如果传入一个可变的元素
user_deque = (["boy1",["boy2","boy4"],"boy3"])
#浅拷贝
user_deque2 = user_deque.copy()
user_deque2[1].append("boy5")
print(user_deque,user_deque2)
输出结果是:
2813269021384 2813269021832
['boy1', 'boy2', 'boy3'] ['boy1', 'boy5', 'boy3']
['boy1', ['boy2', 'boy4', 'boy5'], 'boy3'] ['boy1', ['boy2', 'boy4', 'boy5'], 'boy3']
浅拷贝后,发现两个的id不一样。由于user_deque中的每个元素是字符串,即是不可变元素,所以如果是浅拷贝的话,就会是复制该元素,所以user_deque[1]的值变化了,但是user_deque没有变化。但如果是user_deque中的第二个元素变成了list,即是可变的,就会使得ID指向该新的元素
#如果传入一个可变的元素
user_deque = (["boy1",["boy2","boy4"],"boy3"])
#浅拷贝
# user_deque2 = user_deque.copy()
#深拷贝
user_deque2 = copy.deepcopy(user_deque)
user_deque2[1].append("boy5")
print(user_deque,user_deque2)
深拷贝简单的理解是两个独立的变量,一个变化不会影响另一个变量,故而有如下结论:
- 如果源对象只有一级目录的话,源做任何改动,不影响深浅拷贝对象
- 如果源对象不止一级目录的话,源做任何改动,都要影响浅拷贝,但不影响深拷贝
4.Counter
统计出现的次数,对比字符串中统计函数count功能
from collections import Counter
grade = ["A","A","B","C","B"]
grade_counter = Counter(grade)
print(grade_counter)
# 统计字符串中的个数
str = "uipeadsfakndfakadf"
str_counter = Counter(str)
print(str_counter)
# 合并之后进行统计
str_counter.update("sdkfnaksd")
print(str_counter)
# top n的问题,前n个出现次数最多的
print(str_counter.most_common(2))