深入set和dict

深入set和dict

dict中的抽象关系,collections中的abc,Mapping和MutableMapping(继承Mapping)

 MutableMapping的方法:__setitem__\__delitem__\pop\popitem\clear\update\setdefault,

dict是属于Mapping、MutableMapping类型,而Mapping和序列差不多,都是继承collections,
但Mapping也另外实现了序列没有的其他方法:例如get\keys\items\values

from collections.abc import Mapping,MutableMapping
a_dict = {}
# a_dict并不是继承MutableMapping,而只是实现了MutableMapping的一些方法,在MutableMapping.register(dict)
print(isinstance(a_dict,MutableMapping))
# 结果是True,但不是继承关系
print(dict.mro())
# 字典的继承关系是 [<class 'dict'>, <class 'object'>],并没有mutableMapping

dict常用方法:

clear\copy\fromkeys\get\items\keys\pop\popitem\setdefault\update\values\

a = {"bobby1":{"company":"imooc"},
     "bobby2":{"company":"imooc2"}}

# copy返回浅拷贝,只拷贝了键,而值是公用的,修改后原字典也会受影响,牵一发动全身
new_dict = a.copy()
# dict实现了copy浅拷贝方法,却没有实现deepcopy深拷贝,所以使用深拷贝需要用copy.deepcopy
new_dict["bobby1"]["company"] = "imooc3"

# deepcopy深拷贝,键-值共同拷贝,修改不受影响
new_dict = copy.deepcopy(a)
new_dict["bobby1"]["company"] = "imooc4"

# fromkeys:将iterable对象(如序列)作为键值
# 是dict中的静态方法staticmethod,需要用类名调用即dict.staticmethod
new_list = ["bobby1","bobby2"]
# new_list作为iterable对象,变为键值
new_dict = dict.fromkeys(new_list,{"company":"imooc"})
当取值无key,用get可避免报错,但无法插入字典。
 当字典无key,用setdefault可避免报错,同时插入字典中(先调用get,再设置字典key键和值)
#get:当字典直接通过键去获取值时,经常出现keyerror错误。为了防止这个错误,可使用get方式,设置报错时的默认值,但最后没有插入字典
value = new_dict.get("bobby1",{})

default方法和update方法

 default方法:会调用get(key,d值),如果字典中无key,则返回d值,同时将D[key]=d值(默认值)插入到字典中,最后返回d值
 如果字典中有key,则得到并返回D[key]值,

default_value = new_dict.setdefault("bobby","imooc")

new_dict = {"1":"name",
            "2":"sex"}
value = new_dict.get("3","class")
print(value)
print(new_dict) # 无“3”:"calss"
value = new_dict.setdefault("3","class")
print(value)
print(new_dict) # 有“3”:"class"

# update方法:合并dict或iterable对象
new_dict.update({"4":"home"})
new_dict.update(5="student") # 报错,因为key是变量才能这么用赋值号,5不能作为变量,
new_dict.update(bobby="imooc")
new_dict.update([("bobby1","imooc")])
dict中的子类,dict和list是可继承的,但不建议继承,dict\list都是C语言封装好的
class Mydict(dict):
    def __setitem__(self,key,value):
        super().__setitem__(key,value*2)
my_dict = Mydict(one=1) # 实例化对象时,调用的是__init__方法
print(my_dict) # 出现{"one":1},在实例化对象时,不会去调用__setitem__方法
my_dict["one"] = 1
print(my_dict) # 出现{"one":2},在设置值时,才会调用__setitem__方法
在collection中,有用Python写的UserDict,这个可以继承
class Mydict(UserDict):
    def __setitem__(self,key,value):
        super().__setitem__(key,value*2)
my_dict = Mydict(one=1) # 实例化对象时,调用的是__init__方法,但同时也会调用__setitem__方法
print(my_dict) # 出现{"one":2},在实例化对象时,会调用__setitem__方法
my_dict["one"] = 1
print(my_dict) # 出现{"one":2},在设置值时,会调用__setitem__方法
在collections中,有个defaultdict是dict的子类
from collections import defaultdict
my_dict = defaultdict(dict)
my_value = my_dict["bobby"] # 当字典中没有key时,就会进入__missing__方法,返回空字典
set和frozenset(集合和不可变集合)无序,不重复
s = set("abcde") # 接收可迭代对象
s = set(['a','b','c','d','e'])
print(s) # 顺序是无序的
# 通过add添加元素
s = {'a','b'} # 用{}也是set
# 但frozenset是不可变类型,因此不能使用add,由于frozenset不可变,所以可以作为dict的key
s = frozenset("abcde")
s.add("f")  # 无效的add,因frozenset不可变
update:将两个set合并为一个set
s = set("abcde") 
another_set = set("def")
s.update(another_set) # s发生改变
print(s)
difference:集合中不存在于其他集合中的数据
s = set("abcde")
ano_set = set("defg")
re_set = s.difference(ano_set) # 等同于s-ano_set
print(s) # s没发生改变
print(re_set) # re_set结果是abc

集合中的常见运算:union|并集 &交集 -差集,set和dict使用hash,性能很高

魔法函数__ior__   return self/=value
 __isub__   return self-=value
 __ixon__   return self^=value
re_set = s-ano_set # 差集
re_set = s&ano_set # 交集
re_set = s|ano_set # 并集
 s.is_subset(re_set) :判断s是否为re_set的子集
  • dict和set的实现原理:使用哈希表:将键值(或set里的值)计算成哈希值,作为地址索引,产生哈希冲突可解决

  • 哈希表会申请连续的地址空间,如果空间不够用就会再申请更大的空间,然后把数据复制过去。

  • 查找过程:计算散列值——判断散列值的一部分来定位表元,表元为空(抛出keyerror),表元不为空——健是否相等(有哈希冲突)——相等则返回,不相等则使用散列值的另一部分定位散列表中的另一行

1、不可变对象都可以计算hash值。例如str\frozenset\tuple
2、自己实现的类,可实现__hash__,对象即可哈希
3、dict内存花销大,但是查询速度快。自己定义的对象,或是python内部的对象,都是用dict包装的
4、添加数据有可能改变已有数据的顺序(插入数据可能会重新申请更大的内存,数据顺序有可能改变)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值