轻松初探 Python 篇(五)—dict 和 set 知识汇总

这是「AI 学习之路」的第 5 篇,「Python 学习」的第 5 篇

dict

dict 是 Python 内置的字典类型,熟悉 Java 的同学可以把它类比为 Map。dict 使用键值对来存储(key-value),它的查找速度特别快。

dict 一般用在什么场景呢?假设我们需要根据公司名字查找公司地址,按照我们之前的写法,我们需要先建立两个 list ,一个存储公司名字,一个存储公司总部地址,然后查找公司名字,记录好列表位置,再从地址列表查找到具体元素,你还得保证两个表元素位置必须一一对应。不仅如此,如果表很长,那遍历查找效率将会非常低。

>>> Inc = ['腾讯','阿里','百度']
>>> adress = ['深圳','杭州','北京']
>>> BaiduAdress = adress[Inc.index('百度')]
>>> BaiduAdress
'北京'

我们现在用 dict 实现,使用一个「公司-地址」这样的键值对来进行存储数据,查找的时候,我们只需要输入公司名字,就可以查找到对应的地址,同时,不论 dict 的数据有多少,查找单项的速度都是一样的,而且非常迅速。

>>> Inc_dict = {'腾讯':'深圳','阿里':'杭州','百度':'北京'}
>>> Inc_dict['百度']
'北京'

dict 速度这么快的原理就是使用了空间换取时间的方法,将无限集映射到一个有限集中。通过一个散列函数来计算每一个 key 应该存放在内存中的位置,然后把 value 存储在内存的这个位置上,等到需要取出 key 对应的 value 的时候,只需要通过函数计算出这个位置,然后直接去拿就行了。是不是有点像我们查字典的步骤呢?

通过散列函数求出的最终值就是对应的哈希值(Hash),Java 中的 Map 最常用的实现 HashMap 也是用类似的原理来设计的。Hash 算法也是数据结构中特别重要的一个知识点,所以如果我们计算机的基本功扎实,学哪门语言的时候都是融会贯通的

当然,散列函数本身比较复杂,还要牵扯到冲突的解决问题,简单来说,不同的 key 通过散列函数求得的内存位置可能是一样的,这样就导致了冲突,解决这种冲突的方法有很多,Python 设计者选择了开放定址法,在冲突的时候用另一个不同的函数再计算。在这里我就不深入讨论了,有兴趣的同学可以查阅下相关资料。

我们有很多种方式进行 dict 的初始化,下面几种初始化方式都会获得{"one": 1, "two": 2, "three": 3}

>>> a = dict(one=1,two=2,three=3)
>>> b = {'one':1,'two':2,'three':3}
>>> c = dict(zip(['one','two','three'],[1,2,3]))
>>> d = dict([('two',2),('one',1),('three',3)])
>>> e = dict({'three':3,'one':1,'two':2})
>>> a == b == c == d == e
True

除了通过初始化以外,还可以通过 key 来放入值,再次传入相同 key ,不同 value,将会覆盖前面传入的 value。如果某个 key 不存在,获取该 key 的 value 将会报 KeyError 错误。

>>> Inc_dict['途牛'] = '南京'
>>> Inc_dict['途牛']
'南京'
>>> Inc_dict['途牛'] = '金陵'
>>> Inc_dict['途牛']
'金陵'
>>> Inc_dict['小米']
KeyError:'小米'

为了防止获取 key 不存在的情况。我们可以用 in 来判断 dict 中是否已经存储过以这个 key 来存储的键值对。或者用 get() 方法来获取 value,如果 key 不存在,get() 将返回 None,可以设置一个参数来表示 key 不存在时候的默认返回值。

>>> '小米' in Inc_dict
False
>>> Inc_dict.get('小米')
>>> Inc_dict.get('小米','北京')
北京

通过 pop(key) 方法,来返回并删除对应的 value:

>>> Inc_dict.pop('腾讯')
'深圳'
>>> Inc_dict
{'阿里':'杭州','百度':'北京','途牛':'金陵'}

最后介绍下 dict 的迭代,我们知道 list 迭代可以简单的通过 for 来遍历,dict 迭代需要多做一些操作。

>>> d = {'a':1,'b':2,'c':3}
>>> for key in d:
...     print(key)
...
'a'
'c'
'b'

dict 默认的迭代方式是迭代 key ,如果你需要迭代 value 可以通过 d.values() 来获取 value 的列表

>>> for value in d.values()
...     print(value)
...
1
3
2

当然,你还可以同时迭代 key 和 value

>>> for k, v in d.items():
...     print(k, v)
...
a 1
c 3
b 2

细心的同学一定发现了迭代的顺序和我们初始化定义的顺序是不同的,之前也提到了,dict 内部存放顺序是根据散列函数决定的,所以最后的存放顺序不一定和插入顺序一致,那我们迭代顺序显然是不确定的了。

dict 的设计是典型的以空间换取时间,大家学习 Python 越深入就会发现 Python 的设计里有很多这样的设计, Python 设计的时候,大概已经不是内存最大就 4,500K 的年代了吧(手动嬉笑)。所以 dict 的特点就是,查找和插入的速度非常快,并且不随元素数量的增长而变慢

注意:key 必须是不可变对象(字符串,整数等),如果 key 是 list,就会报错 TypeError: unhashable type: 'list',tuple 虽然是不可变对象,但如果传入的 tuple 元素有可变对象,依然会报错。

>>> d = {'a':1}
>>> d = {'a':1,(1,):2}
>>> d = {'a':1,(1,):2,(1,[1]):3}
TypeError: unhashable type: 'list'

set

set 和 dict 很像,不过 set 不存储键值对,你可以把它想像成只存储 key 的 dict,也可以理解成数学中的无序无重复集合这个概念。所以在 set 中是没有重复元素的,也只能存放不可变元素。我们可以通过一个 list 来创建 set。同样,也是用大括号表示。

>>> s = set([1,2,3])
>>> s
{1,2,3}
>>> s = set([1,2,3,3,3])
>>> s
{1,2,3}

我们可以看到,重复的元素自动被过滤了,同时 set 也是无序的,虽然创建时候显示看起来好像是有序的。我们来看看 set 的一些常用方法。

>>> s.add(4)
>>> s
{1,2,3,4}
>>> s.add(4)
>>> s
{1,2,3,4}

add(key)添加元素到 set 中,但添加重复元素将不会生效

>>> s.remove(4)
>>> s
{1,2,3}
>>> s.remove(4)
KeyError: 4
>>> s1 = {1,2,3}
>>> s2 = {2,3,4}
>>> s1 & s2
{2,3}
>>> s1 | s2
{1,2,3,4}

remove(key)删除元素,如果 key 不存在会报错。同时,set 之前说过可以看成是集合,所以可以做一些交并集的操作。

原文发布于微信公众号 - WeaponZhi(WeaponZhi)

原文发表时间:2017-11-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏软件工程师成长笔记

高德,百度,Google地图定位偏移以及坐标系转换

一般用国际GPS纪录仪记录下来的经纬度,通过GPS定位拿到的原始经纬度,Google和高德地图定位的的经纬度(国外)都是基于WGS-84坐标系的;但是在国内是不...

723
来自专栏数据结构与算法

P1403 [AHOI2005]约数研究

题目描述 科学家们在Samuel星球上的探险得到了丰富的能源储备,这使得空间站中大型计算机“Samuel II”的长时间运算成为了可能。由于在去年一年的辛苦工作...

3565
来自专栏专注研发

poj-1008-玛雅历

上周末,M.A. Ya教授对古老的玛雅有了一个重大发现。从一个古老的节绳(玛雅人用于记事的工具)中,教授发现玛雅人使用了一个一年有365天的叫做Haab的历法...

843
来自专栏HansBug's Lab

Codevs3278[NOIP2013]货车运输

3287 货车运输 2013年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述...

3226
来自专栏desperate633

LintCode 买卖股票的最佳时机 II题目分析代码

假设有一个数组,它的第i个元素是一个给定的股票在第i天的价格。设计一个算法来找到最大的利润。你可以完成尽可能多的交易(多次买卖股票)。然而,你不能同时参与多个交...

411
来自专栏数据结构与算法

2577 医院设置

2577 医院设置 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 Description 设有一棵二叉...

3297
来自专栏小樱的经验随笔

【批处理学习笔记】第十八课:替换字符串

    替换字符串,即将某一字符串中的特定字符或字符串替换为给定的字符串。举例说明其功能: ==================================...

2627
来自专栏北京马哥教育

编码的秘密(python版)

? ? 编码(python版) 最近在学习python的过程中,被不同的编码搞得有点晕,于是看了前人的留下的文档,加上自己的理解,准备写下来,分享给正在...

3027
来自专栏CodingToDie

Python学习(十):有趣的字符串

第10 章 Python 字符串 学的到东西的事情是锻炼,学不到的是磨练 Table of Contents 字符串更新 转义字符 原始字符串 运算 连接 重复...

3477
来自专栏Fish

CCF 最优灌溉

问题描述   雷雷承包了很多片麦田,为了灌溉这些麦田,雷雷在第一个麦田挖了一口很深的水井,所有的麦田都从这口井来引水灌溉。   为了灌溉,雷雷需要建立一些...

1837

扫描关注云+社区