什么是字典
字典(Dictionary)是Python提供的一种常用的数据结构,由键(key)和值(value)成对组成,键和值中间以冒号:隔开,项之间用逗号隔开,整个字典由大括号{}括起来,作为一个快速访问的特征。
字典常用方法
- 创建
# 有很多中创建字典的方法
dic = dict()
dic = {}
- 查看元素
dict[key] # 在 key不存在时会报 KeyValue 的异常
get() # 在 key不存在时会返回None
dict.values() # 返回一个字典所有的值。
dict.items() # 获取字典中的所有键-值对。
dict.keys() # 返回一个字典所有的键。
- 增加\修改 元素
dict[key] = value
- 删除元素
pop(key) # 使用pop删除key
del dic[key] # 使用del删除key
dict.clear() # 清空字典
- 判断key是否存在
# 使用in和not in来判断。
print(key in dic) # key在字典返回True
字典的实现原理
在Python中,字典是通过散列表
或说哈希表
实现的。字典也被称为关联数组
,还称为哈希数组等。也就是说,字典也是一个数组
,但数组的索引是键经过哈希函数处理后得到的散列值
。哈希函数的目的是使键均匀地分布在数组中,并且可以在内存中以O(1)的时间复杂度进行寻址
,从而实现快速查找和修改。通常情况下建立哈希表的具体过程如下:
- 数据添加:把key通过哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。
- 数据查询:再次使用哈希函数将key转换为对应的数组下标,并定位到数组的位置获取value。
哈希函数就是一个映射,因此哈希函数的设定很灵活,只要使得任何关键字由此所得的哈希函数值都落在表长允许的范围之内即可。本质上看哈希函数不可能做成一个一对一的映射关系,其本质是一个多对一的映射,这也就引出了下面一个概念–哈希冲突或者说哈希碰撞。哈希碰撞是不可避免的,但是一个好的哈希函数的设计需要尽量避免哈希碰撞。
# 用hash table 散列表 实现字典
class Dict:
def __init__(self, size=10):
self.size = 0 # 当前散列表大小
self.max_size = size # 散列表最大值
self.table = [None] * self.max_size # 散列表整体
# 哈希方法
def hash_func(self, val):
return hash(val) % self.max_size
# 赋值
def set(self, key, val):
idx = self.hash_func(key)
if self.table[idx]:
for i in range(len(self.table[idx])):
if key == self.table[idx][i][0]:
self.table[idx][i][1] = val
break
else:
self.table[idx] = [[key, val]]
self.size += 1
# 取值
def get(self, key):
idx = self.hash_func(key)
if self.table[idx]:
for i in range(len(self.table[idx])):
if key == self.table[idx][i][0]:
return self.table[idx][i][1]
if i == len(self.table[idx]) - 1:
return None
else:
return None
# 删除元素
def pop(self, key):
idx = self.hash_func(key)
if self.table[idx]:
for i in range(len(self.table[idx])):
if key == self.table[idx][i][0]:
self.table[idx] = None
self.size -= 1
else:
return None
if __name__ == "__main__":
d = Dict()
d.set("name", "安同学")
d.set("age", "18")
d.pop("age")
print(d.get("name")) # 安同学
print(d.get("age")) # None
print(d.size)