05 python深入python的set和dict
dict的abc继承关系
dict属于mapping类型,下面通过查看源码来分析它的继承关系
from collections.abc import Mapping, MutableMapping
查看MutableMapping源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | class MutableMapping(Mapping): __slots__ = () """A MutableMapping is a generic container for associating key/value pairs. This class provides concrete generic implementations of all methods except for __getitem__, __setitem__, __delitem__, __iter__, and __len__. """ @abstractmethod def __setitem__( self , key, value): raise KeyError @abstractmethod def __delitem__( self , key): raise KeyError __marker = object () def pop( self , key, default = __marker): '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised. ''' try : value = self [key] except KeyError: if default is self .__marker: raise return default else : del self [key] return value def popitem( self ): '''D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty. ''' try : key = next ( iter ( self )) except StopIteration: raise KeyError value = self [key] del self [key] return key, value def clear( self ): 'D.clear() -> None. Remove all items from D.' try : while True : self .popitem() except KeyError: pass def update( * args, * * kwds): ''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F. If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v ''' if not args: raise TypeError( "descriptor 'update' of 'MutableMapping' object " "needs an argument" ) self , * args = args if len (args) > 1 : raise TypeError( 'update expected at most 1 arguments, got %d' % len (args)) if args: other = args[ 0 ] if isinstance (other, Mapping): for key in other: self [key] = other[key] elif hasattr (other, "keys" ): for key in other.keys(): self [key] = other[key] else : for key, value in other: self [key] = value for key, value in kwds.items(): self [key] = value def setdefault( self , key, default = None ): 'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D' try : return self [key] except KeyError: self [key] = default return default MutableMapping.register( dict ) |
可以看到MutableMapping继承的是Mapping(不可变) ,最后把dict注册到MutableMapping.中 MutableMapping.register(dict)
可以通过 isinstance 查看一个字典的类型
1 2 3 4 5 | from collections.abc import Mapping, MutableMapping #dict属于mapping类型 a = {} print ( isinstance (a, MutableMapping)) |
测试结果如下
dict的常用方法
copy(这里是浅拷贝)
1 2 3 4 5 6 | a = { "biao1" :{ "company" : "imooc" }, "biao2" : { "company" : "imooc2" } } #copy, 返回浅拷贝 new_dict = a.copy() new_dict[ "bobby1" ][ "company" ] = "imooc3" |
调试结果如下
fromkeys把可迭代的对象转变为dict
1 2 3 | new_list = [ "bobby1" , "bobby2" ] new_dict = dict .fromkeys(new_list, { "company" : "imooc" }) |
调试结果如下
get取值,可以设置一个默认值避免字典中keyerror异常
1 2 | a = { "name1" : "jack" , "name2" : "jane" } value = a.get( "name3" , "not exist" ) |
调试结果如下
setdefault(),和get()相似,不同的是如果没有某个键名,会把此键名和默认值加入到字典中
1 2 3 4 5 | a = { "name1" : "jack" , "name2" : "jane" } # 没有指定键名时 a.setdefault( "name3" , "not exist" ) |
调试结果如下
update(), 可用于添加字典元素
1 2 3 4 5 6 | a = { "name1" : "jack" , "name2" : "jane" } # 直接添加字典方式 a.update({ "name3" : "hong" }) # 使用参数名方式 a.update(name4 = "lilei" , name5 = "mei" ) |
调试结果如下
dict的子类
如果我们想要继承dict重写我们的逻辑 ,不建议继承list和dict 因为他们是c语言写的,我们重写的函数有可能不会生效
1 2 3 4 5 6 7 8 9 10 | #不建议继承list和dict class Mydict( dict ): def __setitem__( self , key, value): super ().__setitem__(key, value * 2 ) my_dict = Mydict(one = 1 ) # 在这个时候没生效 print (my_dict) my_dict[ "one" ] = 1 # 在这个时候生效 print (my_dict) |
打印结果
应该使用python为我们提供的UserDict
1 2 3 4 5 6 7 8 | from collections import UserDict class Mydict(UserDict): def __setitem__( self , key, value): super ().__setitem__(key, value * 2 ) my_dict = Mydict(one = 1 ) pass |
调试结果如下
dict 的子类defaultdict
当我们取值一个不存在的值的时候,它会返回一个 {}
1 2 3 4 | from collections import defaultdict my_dict = defaultdict( dict ) my_value = my_dict[ "bobby" ] |
调试结果如下
内部源码分析
set和frozenset
初始化一个set
1 2 3 4 5 6 | # 使用set关键字 s1 = set ( 'abc' ) # 使用{} s2 = { 'a' , 'b' } print ( type (s1), type (s2)) |
向set中添加元素
1 2 3 | s1 = set ( 'abc' ) s1.add( 'd' ) print (s1) |
使用update()函数更新set
1 2 3 4 | s1 = set ( 'abc' ) s2 = set ( 'xy' ) s1.update(s2) print (s1) |
difference()函数来求两个集合的差集
1 2 3 4 5 6 | s1 = set ( 'abc' ) s2 = set ( 'cd' ) # 相当于s1 - s2 re_set = s1.difference(s2) print (re_set) |
set的数学运算
1 2 3 4 5 6 7 8 9 | s1 = set ( 'abc' ) s2 = set ( 'cd' ) # 差集 print (s1 - s2) # 交集 print (s1 & s2) # 并集 print (s1 | s2) |
issubset()判断集合A是否为集合B的子集
1 2 3 4 | s1 = set ( 'abc' ) s2 = set ( 'c' ) print (s2.issubset(s1)) |
dict和set的实现原理
list和dict的性能比较
dict原理小结
dict找一个值之所以快,是因为他会根据这个键,进行哈希获得偏移量,直接取值,时间复杂度为0(1)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理