python 3.x collections模块

collections模块

  • __all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList', 'UserString', 'Counter', 'OrderedDict', 'ChainMap']
  • 'UserDict', 'UserList','UserString' : python抽象基类里面用到的,不会直接使用
  • collections模块介绍

    • 常用数据结构:  
    • 抽象基类:  
  • tuple的功能

  1. 不可变,iterable
  2. 拆包
     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)
  3. tuple不可变性不是绝对的
    >>  tuple的二级元素可以改变
    >>  元组的元素推荐使用不可变类型的数据,不推荐使用可变类型的数据.
  4. 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  

 

 

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)    收藏  举报

导航