前言:

我一直觉得对我来说学习知识很忌讳不系统。本篇内容与上一篇 自定义序列类是有联系的。

上一篇比较通范的了解了序列类的一些协议和特性,并且有些list的内容。这篇更加具体到set和dict这两个序列类。

以此来了解python序列类的具体应用。(这篇比较简单)(感觉具体比抽象都更容易理解,但是也要学会思考把具体对象抽象化来表达,即提取共性)

content:

1.dict在abc中的序列类型和继承关系

2.dict实现了的常用方法

3.我可不可以继承dict这种序列类?

4.set和frozenset

5.set和dict的原理

==============

1.dict在abc中的序列类型和继承关系

dict在collection.abc中,实际上是属于MutableMapping(可变mapping)类型。

跟上篇对可变序列类继承的分析一样,MutableMapping继承了Mapping的一些功能并且加了一些可变的特性,

Mapping继承了Collection。接下来的继承和上篇的一样。

2.dict实现了的常用方法

如果用的是pycharm,还是用ctrl+b就能跳到python对dict的定义。

常用:

a = {"":{"a":"aa"},
"":{"b":"bb"}} # 清空字典
a.clear() # 浅拷贝字典 浅拷贝虽然可以正常赋值,但是如果 my_dopy_dict 中的值进行了改变,则 a 中的值也会进行对应的改变
my_dopy_dict = a.copy() # 深拷贝 深拷贝则是实实在在的在内存当中声明了一个新的变量
import copy
new_dict = copy.deepcopy(a) # get函数 dict.get(要查找的key,如果没找到对应key的内容返回的数据)
print(a.get("",{1:""})) # {1: '3'} # dict.fromkeys() 函数用于创建一个新字典,以序列 seq 中元素做字典的键 seq可以是可迭代的,value 为字典所有键对应的初始值。
my_list = [1, 2, 3]
my_new_dict = dict.fromkeys(my_list, {"":""}) #{1: {'222': '3434'}, 2: {'222': '3434'}, 3: {'222': '3434'}} # setdefault() 函数和 get()方法 类似,
# 如果键不存在于字典中,将会添加键并将值设为默认值。
# 如果存在,则将会返回该key对应的value
a.setdefault("", "cc") # a= {'1': {'a': 'aa'}, '2': {'b': 'bb'}, '3': 'cc'}
print(a.setdefault("", "cc")) # 返回{'b': 'bb'} # update() 函数把字典dict2的键/值对更新到dict里。
# 如果字典b中有与a相同的key,则会把a中的key对应的value进行更新
# 如果字典b中有a中没有的key,则a会将未有的key与value添加进去
b = {"": "cc", "": "dd"}
a.update(b)
print(a) # {'1': {'a': 'aa'}, '2': 'dd', '3': 'cc'}

3.我可不可以继承dict这种序列类?(dict的子类)

a.如果我偷懒想实现dict这种类型,能不能直接继承这种序列类呢?同理list是否可以?

例:继承dict,并且重写设置dict key的value时调用的魔法函数,使其值变为2倍

class Mydict(dict):
def __setitem__(self, key, value):
super().__setitem__(key, value*2) a=Mydict(b=1)
print(a) a['b']=1
print(a)

输出:

可以发现,原来同样功能和效果的,我们重写方法后,第一种方法去设置key的value值这一操作并没有调用我们重写的方法。

所以并不建议去继承python的这种序列类。

b.有没有什么办法我实在想继承?

python里专门给了个UserDict类,可以实现想要的继承Dict类的效果

from collections import UserDict
class Mydict(UserDict):
def __setitem__(self, key, value):
super().__setitem__(key, value*2) mydict = Mydict(one = 1) # {'one': 2} 调用__setitem__这个魔法函数
mydict["one"] = 2 # {'one': 4} 这种方式也可以调用__setitem__

输出:

 c.python中Dcit实际也有子类实现:defaultdict

使用:

from collections import defaultdict # 这个是dict的子类
mydict = defaultdict(dict)
myvalue = mydict["bai"] # 如果不存在的话,返回{}

输出:

4.set和frozenset

a.两者是啥有啥特点?

set:集合(无序,不重复,可变)

frozenset:不可变集合(无序,不重复,不可变)

frozenset没有改变的方法 一旦初始化了 就不可变了。其中,不可变类型对可变类型的一个特点,不可变类型是可以作为dict的key的。
 
b.set常用操作
a=set('abcdee')
a.add('f')
print(a)
another_set=set('defgh')
#添加数据
#a.update(another_set)
#print(a)
#集合的差集
re_set=a.difference(another_set)
#减法实现于__ior__魔法函数
re_set2=a-another_set
#集合的交集&
re_set3=a&another_set
#集合的并集|
re_set4=a|another_set
print(re_set)
print(re_set2)
print(re_set3)
print(re_set4)
#也可以用if in判断(实现于__contains__魔法函数)
if 'a' in re_set:
print('I am a set')

5.set和dict的原理

之前就提过,set的性能棒的。dict的查询性能远比起list要好。

并且list中随着list数据的增大,查找时间会增大,而dict不会。

这是为什么呢?

因为dict使用hash这种数据结构存储。set也是。

a.dict的散列表

特点:

- dict的key必须是可hash的,不可hash的是不能当成dict的key的,比如list
- python申请内存的时候,会初始化一个小的连续的空空间
- 由上一条可得这样 一定会存在浪费,这时候每次变动操作 会计算剩余空间,剩余空间小于1/3的时候,会重新生成空间并且将现在数据都拷贝过去(rehash)
- 数组比这种链表结构好的地方,就是可以直接根据偏移量来存取,而不用全部开始从头遍历。
(这种结构hash和重hash的策略用在很多地方,包括redis等)
 
b.存储结构了解了,那么数据的查找过程呢?

先计算a的散列值,查找表源是否为空,

因为a是不变的,所以如果表源为空,那么就会抛出key error。

如果表源不为空,也有可能是其他key,查看key是否是要查找的key。

如果是其他key,重新散列循环查找。

c.这种hash结构在python中的特点

- 我们可以用__hash__这个魔法函数实现可hash对象

- dict内存开销比较大,这是hash表的特点。

- 实际上python内部类和对象,都是dict。

- dict存储顺序和元素添加顺序有关。

- 插入数据后检查剩余空间引发的重hash,会影响原来的数据(比如地址)。

PythonI/O进阶学习笔记_5.python的set和dict的更多相关文章

  1. PythonI/O进阶学习笔记_8.python的可迭代对象和迭代器、迭代设计模式

     content: 1.什么是迭代协议 2. 什么是迭代器(Iterator)和可迭代对象(Iterable) 3. 使用迭代器和可迭代对象 4. 创建迭代器和可迭代对象 5. 迭代器设计模式   一 ...

  2. PythonI/O进阶学习笔记_10.python的多线程

     content: 1. python的GIL 2. 多线程编程简单示例 3. 线程间的通信 4. 线程池 5. threadpool Future 源码分析   ================== ...

  3. PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(上)

    content: 上: 1.property动态属性 2.__getattr__和__setattr__的区别和在属性查找中的作用 3.属性描述符 和属性查找过程 4.__new__和__init__ ...

  4. PythonI/O进阶学习笔记_9.python的生成器

     content: 1. 什么是生成器 2. 生成器的实现 3. 生成器的应用   一.生成器简介 1.什么是生成器     在 Python 中,使用了 yield 的函数被称为生成器(genera ...

  5. PythonI/O进阶学习笔记_11.python的多进程

    content: 1. 为什么要多进程编程?和多线程有什么区别? 2. python 多进程编程 3. 进程间通信 =======================================   ...

  6. PythonI/O进阶学习笔记_1.抽象、面向对象、class/object/type

    前言: 是自己在学习python进阶IO学习视频的时候的理解和笔记,因为很多都是本菜鸟学习时候的自己的理解,有可能理解有误. Content: - 抽象的概念和面向对象的概念?想要大概了解python ...

  7. PythonI/O进阶学习笔记_3.2面向对象编程_python的继承(多继承/super/MRO/抽象基类/mixin模式)

    前言: 本篇相关内容分为3篇多态.继承.封装,这篇为第二篇 继承. 本篇内容围绕 python基础教程这段: 在面向对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法.使 ...

  8. PythonI/O进阶学习笔记_6.对象引用,可变性和垃圾回收

    前言: 没有前言了- -......这系列是整理的以前的笔记上传的,有些我自己都忘记我当时记笔记的关联关系了. 记住以后 笔记记了就是用来复习的!!!不看不就啥用没了吗!!! content: 1.p ...

  9. PythonI/O进阶学习笔记_3.1面向对象编程_python的多态和鸭子类型

    前言: 与第一篇的面向对象内容不同的是,第一篇中的面向对象更多的是与类.对象结合起来的概念粗浅理解,就是在编程历史中诞生的一种思想方法. 这篇的面向对象编程,更多落实到在语言设计实现中,是如何体现面向 ...

随机推荐

  1. JavaFx应用 星之小说下载器

    星之小说下载器 说明: 需要jdk环境 目前只支持铅笔小说网,后续添加更多书源,还有安卓版,敬请期待. 喜欢的话,不妨打赏一波! 软件交流QQ群:690380139 断点下载暂未实现,小说下载途中,一 ...

  2. pull解析案例

    此pull解析案例是eclipes的对不对,不知道, private void getXml() { try { InputStream is = getAssets().open("new ...

  3. (十七)c#Winform自定义控件-基类窗体

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  4. (二十七)c#Winform自定义控件-多输入窗体

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  5. 5G标准公布,你很快又要换手机了

    通常,在4G网络环境下,下载一部1G的电影只需要30秒时间,对于经历过2G和3G网络的我们来说已经非常快了. 但是听说,5G环境中下载一部同样的电影,根本不是用秒来计算的,甚至有外媒说,5G的速率会是 ...

  6. Ubuntu18设置mysql的sql_mode

    原因: MySQL 5.7.5及以上功能依赖检测功能.如果启用了ONLY_FULL_GROUP_BY SQL模式(默认情况下),MySQL将拒绝选择列表,HAVING条件或ORDER BY列表的查询引 ...

  7. .net core 实现 api网关 进行 api版本控制

    场景: 由一次大的项目改动引起的app端api不兼容问题,这时候就需要对api做版本控制了,权衡之后因为用户不多,选择了强更,没人想在已经写了8000行代码的单个svc文件中维护好几个版本的接口或者继 ...

  8. Spring源码剖析7:AOP实现原理详解

    前言 前面写了六篇文章详细地分析了Spring Bean加载流程,这部分完了之后就要进入一个比较困难的部分了,就是AOP的实现原理分析.为了探究AOP实现原理,首先定义几个类,一个Dao接口: pub ...

  9. c++ 左移

    maxval = (1 << d) - 1: d=8 意思是2^d-1,相当于1左移d位

  10. Cat应用告警实战

    1. Cat应用告警实战 1.1. 前言 好像是中间件设计者的通病,文档写的都是面向有一定使用各种中间件经验的人,告警模块中每个参数其实都可以详细解释一下,要不然我们理解起来真的很吃力还容易采坑 1. ...