Python中dict(字典)的使用方法和背后的存储逻辑

dict(字典)是Python内置的一个类似于map的基本数据结构。它以键值对的形式存储多组数据,方便查询使用。是一款非常好用,应用范围很广的数据结构。

一、dic的定义

        dict在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。

        dict利用{key: value, key: value, ...}的方式进行键值对的存储。

        举个例子,想象下面的需求:根据同学的名字查找对应的成绩?

        如果使用list来存储,则:

        names = ['Michael', 'Bob', 'Tracy']

        scores = [95, 75, 85]

        print(scores[names.index('Michael')])

        虽然也能解决,但是索引的很繁琐,难懂,费脑子。

        使用dict来存储则有如下:

        d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}  

        print(d['Michael'])


二、dict的使用语法

        (1)添加键值对

        通过key放入数据到dict中

        d['Adam'] = 67

        一个key只能对应一个value,多次对一个key放入value,后面的值会把前面的值冲掉.

        如果key不存在,dict就会报错

        >>> d['Thomas']

        Traceback (most recent call last):  

        File "<stdin>", line 1, in <module>

        KeyError: 'Thomas'

        (2) 如何判断key是否存在?

       第一种方法: 'Thomas' in d

       第二种方法:get()方法

                d.get(‘Thomas’) #如不存在返回None

                d.get(‘Thomas’, value)#如不存在返回value的值

      (3)删除一个key

        pop(key)    例如:d.pop('Bob')

        务必注意,dict内部存放的顺序和key放入的顺序是没有关系的.

        dict中的key必须是不可变对象

                字符串,整数可以。 list不可以。


三、dict的存储机制

dict的存储通过哈希算法(Hash)

通过key计算value的存储位置。为保证hash正确性,key不可变。

那什么是哈希算法呢?

将任意长度的字符串(广义上说:二进制串)通过计算转换为固定长度的字符串。空间换时间。 例如将0-100所有的数字经过哈希函数的运算映射到0-10上。可能会发生冲突。

哈希值越长,冲突的概率越低。

哈希算法避免线性比对的损耗,提升查找(寻址)效率。

举例:根据同学的名字查找成绩。假设待查名字为:n = ‘TracyC’

(1)list做法

names = [‘TracyA', ‘TracyB', 'TracyC']

scores = [95, 75, 85]

查找的效率和

        1.names中每个字符串的长度L1(因为要用n来一个个匹配names中的字符串)以及

        2.names的长度(需要依次比对直到碰到TracyC为止)有关。

list的查找时间随着元素的增加而增加 因为和L1,L2(尤其是L1)有关。元素越多,查找时间越多。这是显而易见的。

(2)dict方法

以一个足够大段的连续空间(类似于数组)存放value的值。预先以一种方法(哈希函数)将每一个key元素的字符串,全部换成同等长度(二进制长度,比如4字节)的一个整数。这个整数,就是存放value的下标。

查找的时候,将待查找的n利用哈希函数换成一个整数i,接下来用i和dict中的key转换后的整数进行比对。比对成功后,将i对应的下标下的数字取出,这个数字就是n对应的value。

这其中省略了最耗时的字符串比较时间L1,至于整数的匹配,是线性的,可以近似认为与元素规模无关。

(3)list和dict查找效率对比实例

举个例子:

names = [‘TracyA', ‘TracyF', 'TracyM']

list做法,要想找到TracyM,需要比对 6 + 6 + 6 = 18次。然后从scores里取出85

dict做法。

d = {' TracyA ': 95, ' TracyF ': 75, ' TracyM ': 85}

事先已经通过哈希函数,将d变成了 d = {580:95, 585:75, 592:85}

这时计算待查的TracyM的哈希值得到592(这次计算原则上不算在查找的时间里)

查找开始,比对592和d中的key值,三次后找到592,根据592这个index,找到存储在某个大的连续空间里的85.

显然,dict要快得多,但是如果哈希表选不好会造成空间的浪费。

空间换时间。580个空间换来15次的时间。

580,585,592这些数字就是一个哈希函数算出来的。

        这个哈希函数就是加法Hash。 也就是把字符串的每一个字符的ASCII码值加起来。

代码如下:

#求n的每一个元素字符串的每一个字符的ascii码值的和。
n = ['TracyA','TracyF','TracyM']
for x in n:
    sum = 0
    for y in x:
        sum += ord(y)
    print(sum)

大家思考一下:

        按照上述的哈希方法进行计算,TracyA和TracAy这两个人,哈希值一样吗? 显然,会出现冲突,需要解决。不再赘述。

        常用的哈希函数 包括:MD5, SHA1, SHA2, SHA-256

        哈希能用来做什么?

        加密!(因为单向,也即几乎不可逆)

        校验!(网站上的防篡改)

        区块链技术

                网站发布一个视频或者文件,发布对应的MD5值。如果你下载后,用MD5加密后的值和发布的不一致,说明已经被篡改。


四、其他的字典变种

1.默认字典defaultdict

为字典附上默认值。传入像int,list,set这样的工厂函数。

例如:

from collections import defaultdict
dic = defaultdict(list)
print(dic[0])

上述程序得到一个空列表。

2.有序字典

dict是哈希算法存储的,因此,并不按照插入的顺序进行迭代,虽然通常情况下,python的编译器都是有序优化。但是,理论上是无序的。

要想让字典有序,需要有序字典OrderedDict

看下面的例子:

from collections import OrderedDict
dic = OrderedDict()
dic['name'] = 'wangwu'
dic['age'] = 19
dic['score'] = 100
for x in dic:
    print(x, dic[x])

运行结果为:

name wangwu
age 19
score 100

学会了就点个赞吧。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎风工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值