PythonI/O进阶学习笔记_5.python的set和dict

系统 1560 0

前言:

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

上一篇比较通范的了解了序列类的一些协议和特性,并且有些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)类型。

PythonI/O进阶学习笔记_5.python的set和dict_第1张图片

PythonI/O进阶学习笔记_5.python的set和dict_第2张图片

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

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

 

2.dict实现了的常用方法

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

PythonI/O进阶学习笔记_5.python的set和dict_第3张图片 PythonI/O进阶学习笔记_5.python的set和dict_第4张图片

常用:

            a = {
            
              "
            
            
              1
            
            
              "
            
            :{
            
              "
            
            
              a
            
            
              "
            
            :
            
              "
            
            
              aa
            
            
              "
            
            
              },
     
            
            
              "
            
            
              2
            
            
              "
            
            :{
            
              "
            
            
              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(
            
              "
            
            
              3
            
            
              "
            
            ,{1:
            
              "
            
            
              3
            
            
              "
            
            })) 
            
              #
            
            
               {1: '3'}
            
            
              #
            
            
               dict.fromkeys() 函数用于创建一个新字典,以序列 seq 中元素做字典的键 seq可以是可迭代的,value 为字典所有键对应的初始值。
            
            
my_list = [1, 2, 3
            
              ]
my_new_dict 
            
            = dict.fromkeys(my_list, {
            
              "
            
            
              222
            
            
              "
            
            :
            
              "
            
            
              3434
            
            
              "
            
            }) 
            
              #
            
            
              {1: {'222': '3434'}, 2: {'222': '3434'}, 3: {'222': '3434'}}
            
            
              #
            
            
               setdefault() 函数和 get()方法 类似,
            
            
              
#
            
            
               如果键不存在于字典中,将会添加键并将值设为默认值。
            
            
              
#
            
            
               如果存在,则将会返回该key对应的value
            
            
a.setdefault(
            
              "
            
            
              3
            
            
              "
            
            , 
            
              "
            
            
              cc
            
            
              "
            
            ) 
            
              #
            
            
               a= {'1': {'a': 'aa'}, '2': {'b': 'bb'}, '3': 'cc'}
            
            
              print
            
            (a.setdefault(
            
              "
            
            
              2
            
            
              "
            
            , 
            
              "
            
            
              cc
            
            
              "
            
            )) 
            
              #
            
            
               返回{'b': 'bb'}
            
            
              #
            
            
               update() 函数把字典dict2的键/值对更新到dict里。
            
            
              
#
            
            
               如果字典b中有与a相同的key,则会把a中的key对应的value进行更新
            
            
              
#
            
            
               如果字典b中有a中没有的key,则a会将未有的key与value添加进去
            
            
b = {
            
              "
            
            
              3
            
            
              "
            
            : 
            
              "
            
            
              cc
            
            
              "
            
            , 
            
              "
            
            
              2
            
            
              "
            
            : 
            
              "
            
            
              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)
          

输出:

PythonI/O进阶学习笔记_5.python的set和dict_第5张图片

可以发现,原来同样功能和效果的,我们重写方法后,第一种方法去设置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__
            
          

输出:

PythonI/O进阶学习笔记_5.python的set和dict_第6张图片

 

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

PythonI/O进阶学习笔记_5.python的set和dict_第7张图片

使用:

            
              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的散列表

PythonI/O进阶学习笔记_5.python的set和dict_第8张图片

特点:

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

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

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

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

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

 

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

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

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

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

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

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

 


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论