创建
字典使用"{}"声明,内容为键值对,可以为任意类型。
创建时需要明确创建方式,注意 “=” 和 “:” 的使用。
>>> dic = {"a": 1, "b": 2, "c": 3}
>>> dic
{'a': 1, 'b': 2, 'c': 3}
#################################################
#还可以:
>>> a = dict(a=1, b=2)
>>> a
{'a': 1, 'b': 2}
#################################################
>>> b = dict([("a", 1),("b", 2)])
>>> b
{'a': 1, 'b': 2}
#################################################
>>> keys = ["a", "b"]
>>> d = dict.fromkeys(keys,"value")
>>> d
{'a': 'value', 'b': 'value'}
#################################################
>>> d = dict.fromkeys(keys)
>>> d
{'a': None, 'b': None}
增删改查
增
>>> md = dict()
>>> md["a"] = 1
>>> md
{'a': 1}
删
>>> mdict={"a" : 1, "b" : 2}
>>> aa = mdict.pop("a", "default")#如果没有"a"键,则让他返回一个"default"
>>> aa
1
>>> mdict
{'b': 2}
>>> mdict = dict(a=1, b=2)
>>> del mdict["a"]
>>> mdict
{'b': 2}
>>> mdict.clear() #清空字典
>>> mdict
{}
>>> del mdict #删除字段引用
>>> mdict
NameError: name 'mdict' is not defined. Did you mean: 'dict'?
改
>>> md = dict(a=1, b = 2,c = 3)
>>> md["b"]=123
>>> md
{'a': 1, 'b': 123, 'c': 3}
查
>>> mdict={"a" : 1, "b" : 2}
>>> mdict["a"]
1
>>> mdict.get("a")
1
#################################################
#有时我们不知道有没有某个键 需要查询但又并不希望返回空值的话
>>> mdict.get("c", 3) #这里的3就是默认返回的结果了
3
>>> mdict #他不会修改字典内容
{'a': 1, 'b': 2}
遍历
>>> md = {'a': 1, 'b': 2, 'c': 3}
>>> for i in md.keys(): #遍历键
... print(i)
...
a
b
c
>>> for v in md.values(): #遍历键
... print(v)
...
1
2
3
>>> for i , v in md.items(): #遍历键值
... print(i,v)
...
a 1
b 2
c 3
值得一提的事
使用字典进行 增 删 查 的效率是比较高的,因为本质上是基于散列表实现的。
但当数据不均匀时,效率也会变低。(平均时间复杂度为O(1),最坏情况下O(n))
py虚拟机的运行重度依赖dict对象,因此对于dict的性能要求特别高。
引入sys库,使用sys.getsizeof(obj)可查看对象占用内存大小。
>>> md = dict() #直接在cmd窗口使用Python 3.11.2 一个空字典,内存大小为64字节
>>> sys.getsizeof(md)
64
>>> md[1] = 1 #增加一个键值对 变为了224
>>> sys.getsizeof(md)
224
>>> del md[1] #删除它 仍然为224
>>> sys.getsizeof(md)
224
>>> md[1] = 1 #多增加几个 仍然为224
>>> md[2] = 2
>>> md[3] = 3
>>> md[4] = 4
>>> md[5] = 5
>>> sys.getsizeof(md)
224
>>> md[6] = 6 #直到此
>>> sys.getsizeof(md)
352
综上,我们可以推断,dict对象也有类似于list的预分配机制。
dict内部哈希表最小长度为8
实践经验表明,一个装满 1/2 到 2/3 之间的哈希表性能较为理想,所以python控制哈希表元素在2/3以内,来平衡内存与执行效率之间的冲突。
因此当一个长度为8的哈希表,装载第6个元素时,就会发生扩容。又因为哈希规模一定为2的幂,所以扩容容量翻倍变为16。
索引数组于键值对数组不相干,他将根据哈希表规模,选择尽量小的整数类型保存索引。容量小于 256 的哈希表 8 位整数保存。小于 65536 的哈希表16位整数保存,以此类推。另:哈希数组规模需满足两个条件:是2的n次幂且大于等于当前元素个数的3倍。键值对数组则永远是哈希数组的2/3。
要使用dict的一个条件是,键是可哈希对象。也就是同时实现了特殊方法__hash__和__eq__的对象。
py内建对象中的不可变对象,都是可哈希的。而像list,dict等可变对象就不行了。
我们自定义的对象默认也是可哈希的,值由对象地址计算得来(python3 +盐)。
python处理哈希冲突的方法是开放地址法。
为了防止哈希攻击,python3加了盐,因此相较与py2,py3更安全些。