python 3.x collections模块
collections模块
- __all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList', 'UserString', 'Counter', 'OrderedDict', 'ChainMap']
- 'UserDict', 'UserList','UserString' : python抽象基类里面用到的,不会直接使用
-
collections模块介绍
- 常用数据结构:
- 抽象基类:
-
tuple的功能
- 不可变,iterable
- 拆包
1 name_tuple = ("python", 18, 175) 2 stu_tuple = ("jayden", 20, 176, "光明路小学") 3 4 # 拆包 5 name, age, heigth = name_tuple 6 7 # 结果 python 18 175 8 print(name, age, heigth) 9 10 # ---------------------------------------------------- 11 12 # 如果只需要名字,其他数据不需要. 13 # 拆包方法 14 stu_name, *stu_other = stu_tuple 15 16 # 结果: jayden [20, 176, '光明路小学'] 17 print(stu_name, stu_other)
- tuple不可变性不是绝对的
>> tuple的二级元素可以改变
>> 元组的元素推荐使用不可变类型的数据,不推荐使用可变类型的数据. - tuple比list好的地方
- immutable的重要性(immutable : 不可变的)
- 性能优化
- 指出元素全部为immutable的tuple会作为常量在编译时确定,因此产生了如此显著的速度差异
- 不可变对象很重要,python在编译的时候会发现tuple对象,因为tuple是不可变对象,将tuple视为常量,这样python在编译的时候就可以把很多值确定下来.
python解释器将python脚本编译成.pyc字节码文件.python字节码文件加载速度比源文件快,所以说如果一些常量在编译的时候确定值.可显著的加速python脚本的速度.
- 线程安全
- tuple是不可变对象,所以线程无法对他进行修改,所以说是线程安全的
- 可以作为dict的key
>> 一个对象只有它的id值不变的情况下,也就是可哈希对象,只有可哈希的对象才能够作为dict的key - 拆包特性
- 性能优化
- 如果拿C语言来类比,tuple对应的是struct,而list对应的是array
- immutable的重要性(immutable : 不可变的)
namedtuple详解(常用:重点掌握)
- 用namedtuple生成一个类而不是对象.
- namedtuple作用:对数据的处理(比如从数据库获取一系列的数据,对数据添加一列,数据的映射等)
1 """举例引出namedtuple""" 2 3 4 class User: 5 def __init__(self, name, age): 6 self.name = name 7 self.age = age 8 9 10 user = User(name="python", age=18) 11 12 # 通过对象点一个属性,来获取数据. 13 # 结果: python 18 14 print(user.name, user.age)
1 """ 2 >> 举例引出namedtuple 3 class User: 4 def __init__(self, name, age): 5 self.name = name 6 self.age = age 7 8 9 user = User(name="python", age=18) 10 11 >> 通过对象点一个属性,来获取数据. 12 print(user.name, user.age) 13 14 15 namedtuple用法: 16 用namedtuple生成一个类而不是对象. 17 18 """ 19 20 from collections import namedtuple 21 22 # 使用namedtuple创建一个类,而不是对象. 23 # namedtuple第一个参数是类名classname 24 # namedtuple第二个参数是类名是可迭代的对象属性序列 25 # namedtuple返回的结果是一个类,用一个类名变量接受,为后续创建对象使用. 26 User = namedtuple("User", ["name", "age", "heigth"]) 27 # 创建User对象. 28 user = User(name="jayden", age=19, heigth=175) 29 30 # 结果: jayden 19 175 31 print(user.name, user.age, user.heigth) 32 33 """ 34 namedtuple作用是生成一个类,那么为什么不使用创建一个class,在__init__()函数中定义属性呢??? 35 因为namedtuple有一个非常大功能,namedtuple是tuple的一个子类,所以说namedtuple相对于自定义class 36 来说,第一代码简单,第二namedtuple节省内存空间,namedtuple少了许多class的内置变量(python解释器在 37 解释class语法时,实际上会为class创建很多变量的.使用namedtuple会省略掉class中很多东西. 38 这样的话namedtuple在内存和效率上都会比创建一个类class要简单,所以说这namedtuple在我们创建一些 39 简单的类的时候就非常的适用,特别是在用做数据处理方面时候,namedtuple用处是非常的大的 40 41 举例: 42 如果从数据库中将user表的数据全部取出然后加一个列"edu".这个时候使用class的话,第一占内存, 43 第二定义class的结构相对比较复杂,代码量增加. 44 如果使用namedtuple来实现会非常的简单,如果使用mysqlclient或者pymysql这种驱动去数据库取数据时, 45 取出来的数据就是一个tuple对象,然而这个tuple直接可以赋值给定义好的类(User = namedtuple("",[])), 46 因为需求非常的简单取出数据加一个列,不需要对数据进行过多的分析或者添加函数.namedtuple对于这种数据 47 处理有一个非常大的优势.将数据库的数据取出为一个tuple之后,然后把它映射成User. 48 """ 49 50 # 比如添加一列"edu" 51 Users = namedtuple("Users", ["name", "age", "heigth", "edu"]) 52 53 # 从数据库中获取一个元组的数据 54 user_tuple = ("hello", 12, 190) 55 56 # tuple直接可以赋值给定义好的类(User = namedtuple("",[])) 57 # 将数据库的数据取出为一个tuple之后,然后把它映射成User. 58 # 可以使用tuple来初始化namedtuple 59 users = Users(*user_tuple, "光明路小学") 60 61 # 字典也可以初始化namedtuple 62 user_dict = {"name": "world", "age": 10, "heigth": 120} 63 user_d = Users(**user_dict, edu="24中") 64 65 # 结果: hello 12 190 光明路小学 66 print(users.name, users.age, users.heigth, users.edu) 67 68 # 结果: world 10 120 24中 69 print(user_d.name, user_d.age, user_d.heigth, user_d.edu)
1 """ 2 namedtuple: 3 _mark(iterable)类方法,参数接收可迭代对象 4 """ 5 6 from collections import namedtuple 7 8 User = namedtuple("User", ["name", "age", "height", "edu"]) 9 user_tuple = ("hello", 12, 190, "光明路小学") 10 11 # users = Users(*user_tuple, "光明路小学") 12 # 使用_make()类方法来实现上一行代码 13 # 这里就不需要再添加*来对tuple拆包 14 user = User._make(user_tuple) 15 print(user.name, user.age, user.height, user.edu) 16 17 user_dict = {"name": "world", "age": 10, "height": 120, "edu": "24中"} 18 19 # user_d = User(**user_dict, edu="24中") 20 # dict字典也是一个可迭代的对象,使用_make()类方法,不用考虑**的问题 21 user_d = User._make(user_dict) 22 # 结果: name age height edu 23 print(user_d.name, user_d.age, user_d.height, user_d.edu) 24 25 user_d_v = User._make(user_dict.values()) 26 # 结果: world 10 120 24中 27 print(user_d_v.name, user_d_v.age, user_d_v.height, user_d_v.edu) 28 29 """ 30 _make()类方法的可迭代参数必须与namedtuple的字段一一对应关系,不像*tuple和**dict可以对应一部分的字段, 31 其他字段使用关键字参数添加即可,_make()类方法的灵活性相比*来说不太好. 32 所以以后开发的时候因情况而定,看看两种方法哪一个更适合你的需求. 33 """
1 """ 2 namedtuple:(主要用作数据处理) 3 _mark(iterable)类方法,参数接收可迭代对象 4 _asdict(self)实例方法 5 将namedtuple对象中的字段转换成字典的形式 6 """ 7 8 from collections import namedtuple 9 10 User = namedtuple("User", ["name", "age", "height", "edu"]) 11 user_tuple = ("hello", 12, 190, "光明路小学") 12 13 user_make = User._make(user_tuple) 14 # debug 15 # user_info_dict={OrderedDict} OrderedDict([('name', 'hello'), ('age', 12), ('height', 190), ('edu', '光明路小学')]) 16 # 'name' (37219216) = {str} 'hello' 17 # 'age' (60320208) = {int} 12 18 # 'height' (46841000) = {int} 190 19 # 'edu' (60320320) = {str} '光明路小学' 20 # __len__ = {int} 4 21 # 得到一个排序的字典. 22 user_info_dict = user_make._asdict() 23 24 # namedtuple继承tuple所以namedtuple也可以拆包赋值 25 # debug: 26 # age = {int} 12 27 # name = {str} 'hello' 28 # other = {list} <class 'list'>: [190, '光明路小学'] 29 name, age, *other = user_make 30 31 print(user_make.name, user_make.age, user_make.height, user_make.edu)
defaultdict功能(常用:重点掌握)
- defaultdict是用C语言写的一个类,所以defaultdict的性能非常的高
- defaultdict是dict的扩展子类
- defaultdict会对某一个键不存在时,添加这个键到字典中并给键赋值一个指定数据类型的默认值
- int --> 0
- str --> ""
- bool --> False
- list --> []
- tuple --> ()
- set --> set()
- dict --> {}
1 """ 2 defaultdict: 3 是用C语言写的一个类,所以defaultdict的性能非常的高 4 """ 5 from collections import defaultdict 6 7 # 使用普通的dict完成统计的功能 8 # 统计某一个字符串在列表中出现了几次 9 user_dict = {} 10 user_list = ["python", "jayden", "python", "jayden", "hello", "world", "python"] 11 12 for user in user_list: 13 if user not in user_dict: 14 user_dict[user] = 1 15 else: 16 user_dict[user] += 1 17 18 # 结果: {'python': 3, 'jayden': 2, 'hello': 1, 'world': 1} 19 print(user_dict) 20 21 """ 22 有没有什么办法将for语句里面的代码精简呢??? 23 if...else...过多影响代码的可读性 24 有没有更好的方法,使for语句里面的代码更加清晰简单呢??? 25 """
1 # 使用普通的dict完成统计的功能 2 # 统计某一个字符串在列表中出现了几次 3 user_dict = {} 4 user_list = ["python", "jayden", "python", "jayden", "hello", "world", "python"] 5 6 for user in user_list: 7 # 在python dict里面提供一个方法setdefault(key, defaultValue),如果对应的key没有值的情况下,设置默认值 8 # 比if语句判断的效率高,少做一次对字典的查询 9 user_dict.setdefault(user, 0) 10 user_dict[user] += 1 11 12 # 结果: {'python': 3, 'jayden': 2, 'hello': 1, 'world': 1} 13 print(user_dict) 14 15 """ 16 再一次对上述代码进行简化 17 """
1 from collections import defaultdict 2 3 # defaultdict()传递一个可调用的对象参数list 4 default_dict = defaultdict(list) 5 6 # debug 7 # 按普通的字典考虑,如果指定的key不存在,会报错KeyError,但是使用defaultdict则没有报错. 8 # 反而给key为"python"的键,设置了一个默认值(空列表) 9 # default_dict = {defaultdict} defaultdict(<class 'list'>, {'python': []}) 10 # 'python' (42426976) = {list} <class 'list'>: [] 11 # __len__ = {int} 1 12 default_dict["python"] 13 pass
1 from collections import defaultdict 2 3 # defaultdict()传递一个可调用的对象参数int 4 default_dict = defaultdict(int) 5 6 # debug 7 # 按普通的字典考虑,如果指定的key不存在,会报错KeyError,但是使用defaultdict则没有报错. 8 # 反而给key为"python"的键,设置了一个默认值0 9 # default_dict = {defaultdict} defaultdict(<class 'int'>, {'python': 0}) 10 # 'python' (42885840) = {int} 0 11 # __len__ = {int} 1 12 default_dict["python"] 13 pass
1 from collections import defaultdict 2 3 # 使用defaultdict完成统计的功能 4 # 统计某一个字符串在列表中出现了几次 5 default_dict = defaultdict(int) 6 user_list = ["python", "jayden", "python", "jayden", "hello", "world", "python"] 7 8 for user in user_list: 9 # 代码的严谨性提高 10 # 不需要if语句判断 11 # 12 default_dict[user] += 1 13 14 # 结果: defaultdict(<class 'int'>, {'python': 3, 'jayden': 2, 'hello': 1, 'world': 1}) 15 print(default_dict)
1 """ 2 需求: 3 如果需要这种格式的初始化字典怎样完成??? 4 group_dict = { 5 "group1": { 6 "name": "", 7 "age": 0 8 } 9 } 10 11 使用defaultdict(dict)这种方式来完成dict嵌套dict是做不到的. 12 13 如何做一个dict嵌套dict的数据结构??? 14 """ 15 from collections import defaultdict 16 17 18 def gen_default(): 19 return { 20 "name": "", 21 "age": 0 22 } 23 24 25 default_dict = defaultdict(gen_default) 26 27 # debug: 28 # default_dict = {defaultdict} defaultdict(<function gen_default at 0x0000000003A267B8>, 29 # {'group1': {'name': '', 'age': 0}}) 30 # 31 # 'group1' (61676320) = {dict} {'name': '', 'age': 0} 32 # 'name' (4778896) = {str} '' 33 # 'age' (61676264) = {int} 0 34 # __len__ = {int} 2 35 default_dict["group1"] 36 pass
deque功能
- deque双端队列
- 用C语言来实现的类
- deque提供一些方法可以在队列的头部和尾部进行操作.
- deque与list一样,一般情况下用来保存相同的数据类型的数据
- deque具体的应用场景(举一个示例):
- from queue import Queue
- queue.py中的put()方法内部一行代码 self._put(item) --> def _put(self, item): self.queue.append(item) --> def _init(self, maxsize): self.queue = deque()
- deque比list更重要的特性:
- deque是线程安全的,是由GIL来保护的 (GIL:全局解释器锁)
- list是线程不安全的
- 在做多线程编程时,可以使用deque线程安全的特性
1 """ 2 通过示例引出deque 3 """ 4 user_list = ["python", "java"] 5 # pop()方法作用是默认移除列表最后一个元素并将其返回给指定变量.可以指定索引值移除元素并返回. 6 # list不能随心所欲的在队头进行操作.需要指定索引值. 7 user_pop = user_list.pop() 8 9 # 结果: java ['python'] 10 print(user_pop, user_list)
1 """ 2 deque双端队列初始化 3 """ 4 from collections import deque 5 6 user_list = ["python", "java"] 7 user_tuple = ("hello", "world") 8 user_dict = {"jayden": 18, "june": 12} 9 10 # deque()初始化需要一个可迭代的参数 11 # 任意一个可迭代的对象都能让deque初始化 12 deque_list = deque(user_list) 13 deque_tuple = deque(user_tuple) 14 deque_dict = deque(user_dict) 15 deque_dict_value = deque(user_dict.values()) 16 17 # 结果: deque(['python', 'java']) 18 print(deque_list) 19 20 # 结果: deque(['hello', 'world']) 21 print(deque_tuple) 22 23 # 结果: deque(['jayden', 'june']),字典是将所有的key组成双端队列 24 print(deque_dict) 25 26 # 结果: deque([18, 12]) 27 print(deque_dict_value)
1 """ 2 在实际应用时,我们把list当做容器,容器一般保存同一类型的数据. 3 tuple虽然像list一样可以存储数据,实际上一个tuple我们把它当成简单的对象来处理 4 """ 5 6 from collections import deque 7 8 user_list = [] 9 10 # 把tuple当做一个简单的对象来处理(tuple存储User对象的name, age, height等属性) 11 user_tuple = ("jayden", 18, "175cm") 12 13 # list当做容器,保存同一种数据类型的数据 14 user_list.append(user_tuple)
1 """ 2 deque的操作方法 3 appendleft()方法:在deque双端队列头部添加一个元素 4 """ 5 6 from collections import deque 7 8 user_list = ["python", "java", "android", "ios"] 9 10 # 初始化deque 11 deque_list = deque(user_list) 12 13 # 队列头部添加元素 14 deque_list.appendleft("dart") 15 16 # 结果: deque(['dart', 'python', 'java', 'android', 'ios']) 17 print(deque_list)
1 """ 2 deque的操作方法 3 copy()方法:浅拷贝一个deque 4 """ 5 6 from collections import deque 7 8 user_list = ["python", "java", "android", "ios"] 9 10 # 初始化deque 11 user_deque = deque(user_list) 12 13 user_deque_copy = user_deque.copy() 14 15 # 40164680 41839632 --> id值不同,证明不是同一个对象 16 print(id(user_deque), id(user_deque_copy)) 17 18 # 将浅拷贝的user_deque_copy的第二个元素进行修改,user_deque中的元素是不会改变的 19 user_deque_copy[1] = "java_copy" 20 21 # 结果: deque(['python', 'java', 'android', 'ios']) 22 print(user_deque) 23 24 # 结果: deque(['python', 'java_copy', 'android', 'ios']) 25 print(user_deque_copy) 26 27 """ 28 以上示例,当浅拷贝一个deque,修改拷贝后的deque的元素,不影响原有的deque的元素. 29 python将现有的拷贝deque与原有的deque做了隔离. 30 那为什么还叫浅拷贝呢??? 31 32 浅拷贝是针对可变对象而言的 33 """
1 """ 2 浅拷贝是针对可变对象而言的 3 4 浅拷贝只拷贝列表里面的元素,如果列表中有可变类型的元素,python将不会拷贝可变元素,而是直接指向这个可变类型的元素. 5 如果是不可变元素,python会直接复制一个不可变元素,这就是浅拷贝 6 """ 7 8 from collections import deque 9 10 user_list = ["python", ["java", "java1", "java2"], "android", "ios"] 11 12 # 初始化deque 13 user_deque = deque(user_list) 14 15 user_deque_copy = user_deque.copy() 16 17 user_deque_copy[1].append("java3") 18 19 # 结果: deque(['python', ['java', 'java1', 'java2', 'java3'], 'android', 'ios']) 20 print(user_deque) 21 22 # 结果: deque(['python', ['java', 'java1', 'java2', 'java3'], 'android', 'ios']) 23 print(user_deque_copy)
1 """ 2 深拷贝(import copy) 3 4 对可变数据类型的数据以及不可变数据类型的数据都进行拷贝.(而浅拷贝对可变数据类型的数据只是指向而不是拷贝) 5 6 """ 7 8 from collections import deque 9 import copy 10 11 user_list = ["python", ["java", "java1", "java2"], "android", "ios"] 12 13 # 初始化deque 14 user_deque = deque(user_list) 15 16 # 深拷贝 17 deepcopy_deque = copy.deepcopy(user_deque) 18 19 deepcopy_deque[1].append("java8") 20 21 # 结果: deque(['python', ['java', 'java1', 'java2'], 'android', 'ios']) 22 print(user_deque) 23 # 结果: deque(['python', ['java', 'java1', 'java2', 'java8'], 'android', 'ios']) 24 print(deepcopy_deque)
1 """ 2 deque的操作方法 3 extend()方法:将两个deque合并 4 """ 5 6 from collections import deque 7 8 user_name = ["python", "java", "android", "ios"] 9 user_name1 = ["python1", "java1", "android1", "ios1"] 10 user_age = [18, 25, 33, 9] 11 12 # 初始化deque 13 user_name_deque = deque(user_name) 14 user_name_deque1 = deque(user_name1) 15 user_age_deque = deque(user_age) 16 17 # 合并两个deque 18 user_name_deque.extend(user_name_deque1) 19 20 # 此处pycharm提示,预期类型是Iterable[str],而你提供的是Iterable[int]. 21 # 22 # This inspection detects type errors in function call expressions. 23 # 此检查检测函数调用表达式中的类型错误。 24 # Due to dynamic dispatch and duck typing , this is possible in a limited but useful number of cases. 25 # 由于动态分派和duck类型,这在有限但有用的情况下是可能的。 26 # Types of function parameters can be specified in docstrings or in python3 function annotations 27 # 函数参数的类型可以在docstring或python3函数注释中指定 28 user_name_deque.extend(user_age_deque) 29 30 # deque(['python', 'java', 'android', 'ios', 'python1', 'java1', 'android1', 'ios1', 18, 25, 33, 9]) 31 print(user_name_deque)
1 """ 2 deque的操作方法 3 extend()方法:将两个deque合并 4 """ 5 6 from collections import deque 7 8 user_name = ["python", "java", "android", "ios"] 9 10 # 初始化deque 11 user_name_deque = deque(user_name) 12 13 user_name_deque.insert(1, "hello") 14 15 # 结果: deque(['python', 'hello', 'java', 'android', 'ios']) 16 print(user_name_deque)
1 """ 2 deque的操作方法 3 reverse()方法:将整个deque顺序翻转 4 """ 5 6 from collections import deque 7 8 user_name = ["python", "java", "android", "ios"] 9 10 # 初始化deque 11 user_name_deque = deque(user_name) 12 13 user_name_deque.reverse() 14 15 # 结果: deque(['ios', 'android', 'java', 'python']) 16 print(user_name_deque)
1 """ 2 deque的操作方法 3 rotate()方法:将右面的元素移动到左面,默认一次,可指定次数 4 """ 5 6 from collections import deque 7 8 user_name = ["python", "java", "android", "ios"] 9 10 # 初始化deque 11 user_name_deque = deque(user_name) 12 13 # 默认移动一次 : deque(['ios', 'python', 'java', 'android']) 14 user_name_deque.rotate() 15 16 # 指定移动2次 : deque(['android', 'ios', 'python', 'java']) 17 user_name_deque.rotate(2) 18 19 print(user_name_deque)
Counter功能
- dict的一个子类
- 用于统计大量数据的数量
- 初始化Counter的方法
- c = Counter() # a new, empty counter
- c = Counter('abcdeabcdabcaba') # 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
- Counter的初始化,就完成对数据的统计,并且把统计的数据从大到小排列起来
1 from collections import Counter 2 3 user_list = ["python", "java", "php", "Go", "python", "java", "php", "python", "java", "python"] 4 # Counter的初始化,就完成对数据的统计,并且把统计的数据从大到小排列起来 5 user_counter = Counter(user_list) 6 7 # 结果: Counter({'python': 4, 'java': 3, 'php': 2, 'Go': 1}) 8 print(user_counter) 9 10 # 获取排名前二的数据(top n的问题) 11 user_common = user_counter.most_common(2) 12 13 # 结果: [('python', 4), ('java', 3)] 14 print(user_common) 15 16 # ---------------------------------------------------------------------------------------------- 17 18 a_str = "abcdeabcdabcaba" 19 20 # Counter的初始化,就完成对数据的统计,并且把统计的数据从大到小排列起来 21 counter_str = Counter(a_str) 22 23 # 结果: Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1}) 24 print(counter_str) 25 26 # 获取排名前三的数据(top n的问题) 27 common_str = counter_str.most_common(3) 28 29 # 结果: [('a', 5), ('b', 4), ('c', 3)] 30 print(common_str) 31 32 # most_common()空参时,输出所有的排序 33 common_str_all = counter_str.most_common() 34 35 # [('a', 5), ('b', 4), ('c', 3), ('d', 2), ('e', 1)] 36 print(common_str_all)
1 """ 2 Counter的update()方法 3 将两个可迭代的对象或者字典或者关键字参数或者Counter对象合并进行数量统计 4 """ 5 from collections import Counter 6 7 a_str = "abcdeabcdabcaba" 8 b_str = "aoeiuvaoeiuaoeiaoeaoa" 9 10 # Counter的初始化,就完成对数据的统计,并且把统计的数据从大到小排列起来 11 counter_str = Counter(a_str) 12 13 # 合并再次统计(传递可迭代的对象) 14 counter_str.update(b_str) 15 16 # Counter({'a': 11, 'e': 5, 'o': 5, 'b': 4, 'c': 3, 'i': 3, 'd': 2, 'u': 2, 'v': 1}) 17 print(counter_str) 18 19 20 counter_str_a = Counter("zxcvbzxcvzxczxz") 21 # update()接收一个Counter对象,因为Counter是字典的子类,字典是可迭代的对象,所以可以传递Counter对象 22 counter_str.update(counter_str_a) 23 # Counter({'a': 11, 'c': 6, 'b': 5, 'e': 5, 'o': 5, 'z': 5, 'x': 4, 'i': 3, 'v': 3, 'd': 2, 'u': 2}) 24 print(counter_str)
OrderedDict功能
- 记住插入顺序的字典
- OrderedDict继承dict
1 from collections import OrderedDict 2 3 user_ordered_dict = OrderedDict() 4 5 user_ordered_dict["p"] = "python" 6 user_ordered_dict["j"] = "java" 7 user_ordered_dict["a"] = "android" 8 9 # 输出的顺序与插入的顺序是一样的 10 # 结果: OrderedDict([('p', 'python'), ('j', 'java'), ('a', 'android')])记住插入的顺序 11 print(user_ordered_dict)
1 """ 2 在python3中dict和OrderedDict都是记住插入顺序的 3 所以字典dict也是有序的 4 """ 5 6 user_ordered_dict = dict() 7 8 user_ordered_dict["p"] = "python" 9 user_ordered_dict["j"] = "java" 10 user_ordered_dict["a"] = "android" 11 user_ordered_dict["b"] = "bbbb" 12 user_ordered_dict["c"] = "cccc" 13 14 15 # 结果: {'p': 'python', 'j': 'java', 'a': 'android', 'b': 'bbbb', 'c': 'cccc'}记住插入的顺序 16 print(user_ordered_dict)
1 """ 2 在python2中dict是无序的, OrderedDict是记住插入顺序的 3 在python3中dict和OrderedDict都是记住插入顺序的 4 既然在python3中dict与OrderedDict都是记住插入顺序的, 那OrderedDict的优势是??? 5 6 def popitem(self, last=True): 7 将移除的对象以元组(元组包含两个元素key,value)的形式返回 8 last为True移除字典最后一个元素 9 last为False移除字典第一个元素 10 11 然而dict的def popitem(self)只能移除最后一个元素,不能移除第一个元素 12 """ 13 from collections import OrderedDict 14 15 user_ordered_dict = OrderedDict() 16 17 user_ordered_dict["p"] = "python" 18 user_ordered_dict["j"] = "java" 19 user_ordered_dict["a"] = "android" 20 21 # 结果: ('a', 'android') 22 print(user_ordered_dict.popitem()) 23 24 # 结果: OrderedDict([('p', 'python'), ('j', 'java')]) 25 print(user_ordered_dict)
1 """ 2 在python2中dict是无序的, OrderedDict是记住插入顺序的 3 在python3中dict和OrderedDict都是记住插入顺序的 4 既然在python3中dict与OrderedDict都是记住插入顺序的, 那OrderedDict的优势是??? 5 6 def popitem(self, last=True): 7 将移除的对象以元组(元组包含两个元素key,value)的形式返回 8 last为True移除字典最后一个元素 9 last为False移除字典第一个元素 10 11 然而dict的def popitem(self)只能移除最后一个元素,不能移除第一个元素 12 """ 13 from collections import OrderedDict 14 15 user_ordered_dict = OrderedDict() 16 17 user_ordered_dict["p"] = "python" 18 user_ordered_dict["j"] = "java" 19 user_ordered_dict["a"] = "android" 20 21 # 结果: ('a', 'android') 22 print(user_ordered_dict.popitem()) 23 24 # 结果: OrderedDict([('p', 'python'), ('j', 'java')]) 25 print(user_ordered_dict)
1 """ 2 在python2中dict是无序的, OrderedDict是记住插入顺序的 3 在python3中dict和OrderedDict都是记住插入顺序的 4 既然在python3中dict与OrderedDict都是记住插入顺序的, 那OrderedDict的优势是??? 5 6 def move_to_end(self, key, last=True): 7 将指定key的元素移动到字典的最后面(last默认为True) 8 last = False将指定key的元素移动到字典的最前面 9 如果指定的key不存在,会抛出异常KeyError 10 11 dict没有此方法. 12 """ 13 from collections import OrderedDict 14 15 user_ordered_dict = OrderedDict() 16 17 user_ordered_dict["p"] = "python" 18 user_ordered_dict["j"] = "java" 19 user_ordered_dict["a"] = "android" 20 21 # 结果: None 22 print(user_ordered_dict.move_to_end("p")) 23 24 # 结果: OrderedDict([('j', 'java'), ('a', 'android'), ('p', 'python')]) 25 print(user_ordered_dict) 26 27 # last=False,将指定元素移动到字典的最前面 28 user_ordered_dict.move_to_end("a", False) 29 30 # 结果: OrderedDict([('a', 'android'), ('j', 'java'), ('p', 'python')]) 31 print(user_ordered_dict)
ChainMap功能
- 作用 : 将多个dict合并起来
- 功能 : 访问多个dict就像访问一个dict一样,操作方便
- ChainMap并不是把多个合并的dict,变成一个dict,而是对多个合并的dict添加了一个迭代器.同时并没有把多个合并的字典拷贝到另外一个新的结构里面.
1 """ 2 举例引出ChainMap 3 """ 4 user_dict1 = {"a": "python", "b": "java"} 5 user_dict2 = {"c": "java", "d": "php"} 6 7 # 使用一般的方法遍历这两个字典(for...in...) 8 for key, value in user_dict1.items(): 9 print(key, value) 10 11 for key, value in user_dict2.items(): 12 print(key, value) 13 14 # 结果: 15 # a python 16 # b java 17 # c java 18 # d php 19 20 # 如果有大量的字典需要遍历的话怎么办??? 21 # 重复的写大量的for循环??? 22 # 有没有什么数据结构将所有的dict全部合并到一个地方,然后直接进行一次遍历即可呢???
1 """ 2 ChainMap 3 作用 : 将多个dict合并起来 4 """ 5 6 from collections import ChainMap 7 8 user_dict1 = {"a": "python", "b": "java"} 9 user_dict2 = {"c": "java", "d": "php"} 10 11 new_dict = ChainMap(user_dict1, user_dict2) 12 13 # ChainMap({'a': 'python', 'b': 'java'}, {'c': 'java', 'd': 'php'}) 14 print(new_dict) 15 16 for key, value in new_dict.items(): 17 print(key, value) 18 19 # 结果: chainmap无序 20 # d php 21 # b java 22 # a python 23 # c java
1 """ 2 ChainMap合并多个dict,如果多个字典中有相同的key,那么会取第一个dict的key和value 3 其他后面相同key的键值对不会显示. 4 """ 5 6 from collections import ChainMap 7 8 # 两字典中有相同的key 9 user_dict1 = {"a": "python", "b": "java"} 10 user_dict2 = {"b": "android", "d": "php"} 11 user_dict3 = {"b": "C++", "c": "php"} 12 13 new_dict = ChainMap(user_dict1, user_dict2, user_dict3) 14 15 # 结果: ChainMap({'a': 'python', 'b': 'java'}, {'b': 'android', 'd': 'php'}, {'b': 'C++', 'c': 'php'}) 16 print(new_dict) 17 18 for key, value in new_dict.items(): 19 print(key, value) 20 21 # 结果: 只显示第一个key为b的键值对 22 # b java 23 # a python 24 # c php 25 # d php
1 """ 2 def new_child(self, m=None): 3 在原有的字典的前面添加一个字典,返回一个新的字典 4 """ 5 6 from collections import ChainMap 7 8 # 两字典中有相同的key 9 user_dict1 = {"a": "python", "b": "java"} 10 user_dict2 = {"b": "android", "d": "php"} 11 12 new_dict = ChainMap(user_dict1, user_dict2) 13 14 # 在原有的字典的前面添加一个字典,返回一个新的字典 15 new_child_dict = new_dict.new_child({"f": "aa"}) 16 17 # 结果: ChainMap({'f': 'aa'}, {'a': 'python', 'b': 'java'}, {'b': 'android', 'd': 'php'}) 18 print(new_child_dict) 19 20 for key, value in new_child_dict.items(): 21 print(key, value) 22 23 # 结果: 24 # f aa 25 # b java 26 # a python 27 # d php
1 """ 2 def new_child(self, m=None): 3 在原有的字典的前面添加一个字典,返回一个新的字典 4 5 如果在原有的字典前面添加的子字典的key在原有的字典中存在,那么原有字典中重复的key将全都不显示. 6 因为new_child()方法将子字典添加在原有字典的第一个位置,所以后面重复的key的键值对都不显示. 7 """ 8 9 from collections import ChainMap 10 11 # 两字典中有相同的key 12 user_dict1 = {"a": "python", "b": "java"} 13 user_dict2 = {"b": "android", "d": "php"} 14 15 new_dict = ChainMap(user_dict1, user_dict2) 16 17 # 在原有的字典的前面添加一个字典,返回一个新的字典 18 new_child_dict = new_dict.new_child({"b": "aa"}) 19 20 # 结果: ChainMap({'b': 'aa'}, {'a': 'python', 'b': 'java'}, {'b': 'android', 'd': 'php'}) 21 print(new_child_dict) 22 23 for key, value in new_child_dict.items(): 24 print(key, value) 25 26 # 结果: 27 # a python 28 # b aa 29 # d php
1 """ 2 maps 3 将合并的字典以列表的形式表现出来.然后对列表进行操作 4 maps是指向所有合并的dict的,而不是拷贝 5 """ 6 7 from collections import ChainMap 8 9 # 两字典中有相同的key 10 user_dict1 = {"a": "python", "b": "java"} 11 user_dict2 = {"b": "android", "d": "php"} 12 13 new_dict = ChainMap(user_dict1, user_dict2) 14 15 # 结果: [{'a': 'python', 'b': 'java'}, {'b': 'android', 'd': 'php'}] 16 print(new_dict.maps) 17 18 # 证明: maps是指向所有合并的dict的,而不是拷贝 19 # 修改new_dict.maps[0]['b']的值,user_dict1元素的值也随之改变 20 new_dict.maps[0]['b'] = "ios" 21 # 结果: [{'a': 'python', 'b': 'ios'}, {'b': 'android', 'd': 'php'}] 22 print(new_dict.maps) 23 # 结果: {'a': 'python', 'b': 'ios'} 24 print(user_dict1)
********
posted on 2019-04-04 13:59 jaydenjune 阅读(130) 评论(0) 收藏 举报
浙公网安备 33010602011771号