五 Python基础之dict和set

前言

Python中内置了dictsetdict也就是我们常说的字典dict的最大好处就是取值非常快,给定一个key,我们可以快速获取到它对应的value。也正是如此,dict也被广泛应用在我们的实际开发当中。

set,顾名思义,也就是集合,和我们初中学习过的数学知识一样,集合具有确定性无序性互异性,回顾一下:

  • 确定性

给定一个集合,任给一个元素,该元素或者属于或者不属于该集合,二者必居其一,不允许有模棱两可的情况出现

  • 无序性

元素之间没有顺序,都是无序的。

  • 互异性

给定一个集合,元素不允许重复,集合中的元素都是不相同的。

dict

初始化

dict可以使用字面量初始化,例如

1
dic = {'key1': 'value1', 'key2': 666}

有趣的是,python的字典可以是基本数据类型或一些不可变类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> dic = {'key1': 'value1', 1: 'one', False: 'False', _: '_'}
>>> dic['key1']
'value1'
>>> dic[1] // 可以使用基本数据类型作为key
'one'
>>> dic[False] // 可以使用bool值作为key
'False'
>>> dic[_] // 可以使用下划线_作为key
'_'
>>> dic[0] // 当key为bool值时,可以用0代表False取值,可以用1代表True取值
'False'
>>> dic[True] // 当key为1或者0时,可以用True代表1取值,可以用False代表0取值
'one'

但是,要注意的是,当key0时,如果使用False作为key添加到字典,则字典的key还是以0为准,但是值会覆盖之前的值,当key1时,也是同一个道理,例如:

1
2
3
4
5
6
7
8
9
>>> dic = {1: 'a', 0: 'b'}
>>> dic
{1: 'a', 0: 'b'}
>>> dic[True] = 'True'
>>> dic
{1: 'True', 0: 'b'}
>>> dic[False] = 'False'
>>> dic
{1: 'True', 0: 'False'}

同样地,当keyTrueFalse时,添加10作为key添加到字典,仍然是以TrueFalsekey,只是值会被覆盖,例如:

1
2
3
4
5
6
7
>>> dic = {True: 'a', False: 'b'}
>>> dic[1] = 666
>>> dic
{True: 666, False: 'b'}
>>> dic[0] = 555
>>> dic
{True: 666, False: 555}

也就是说,当你的key1时,这时往字典添加True作为key时,Python内部会将你的True转化为1,然后判断原来的dic里面已经有1,因此key保持不变,值被覆盖。反之,如果用bool值作为key,再往里面添加10作为key的时候,Python内部会转化成bool值的key

添加值

直接通过赋值的方式往字典中添加键值对,比如:

1
2
3
4
>>> dic = {'key1': 'value1', 'key2': 'value2'}
>>> dic['key3'] = 'value3'
>>> dic
{'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}

判断key是否存在

  • key in dict

使用key in dict的形式来判断key是否存在于字典dict中,例如:

1
2
3
4
5
dic = {'key1': 'value1', 'key2': 'value2'}
if 'key2' in dic:
print('dic中存在key2')
else:
print('dic中不存在key2')

输出:

1
dic中存在key2
  • dic.get(key)

第二种方法就是通过dic.get(key)的形式判断,如果key存在,将返回key对应的value,如果key不存在,则返回None,也可以指定当key不存在时,返回特定的值。例如:

1
2
3
4
5
6
7
8
9
dic = {'key1': 'value1', 'key2': 'value2'}
ret = dic.get('key2')
print('ret = %s' % ret)

ret1 = dic.get('key3')
print('ret1 = %s' % ret1)

ret2 = dic.get('key4', -9999)
print('ret2 = {0}'.format(ret2))

输出:

1
2
3
4
➜  Desktop python3 demo.py
ret = value2
ret1 = None
ret2 = -9999

删除元素

字典的删除元素方法和数组是类似的,直接使用pop(key)的形式,pop(key)删除并返回所删除的key对应的value,但是如果key不存在就会报错:

1
2
3
4
5
6
7
8
9
>>> dic = {'a': 1, 'b': 2}
>>> dic.pop('a')
1
>>> dic
{'b': 2}
>>> dic.pop('c')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'c'

特点

  • 查找速度快(以空间换时间)
  • 占用空间大,浪费内存较多
  • key必须是不可变对象

为什么要求key是不可变,引用廖雪峰的官方网站的描述就是:

因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。
要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。比如,list是可变的,就不能作为key

set

创建集合

Python中,创建集合需要一个list数组作为数组,这一点很有趣:

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

添加元素

使用add(key)的形式来添加元素到集合中

1
2
3
4
>>> mySet = set([1, 2, 3])
>>> mySet.add(4)
>>> mySet
{1, 2, 3, 4}

删除元素

使用remove(key)的形式直接删除元素

1
2
3
4
>>> mySet = set([1, 2, 3])
>>> mySet.remove(2)
>>> mySet
{1, 3}

交集

使用&符号求两个集合的交集

1
2
3
4
>>> mySet = set([1,2,3])
>>> yourSet = set([2, 3, 4])
>>> mySet & yourSet
{2, 3}

并集

使用|符号求两个集合的并集

1
2
3
4
>>> mySet = set([1,2,3])
>>> yourSet = set([2, 3, 4])
>>> mySet | yourSet
{1, 2, 3, 4}

注意:setdict的唯一区别是没有存储对应的value,因为集合具有互异性,为了保证没有重复的元素,因此集合内不可以添加不可变对象

小结

  • dictsetkey必须不可变,因为要保证可哈希
  • 通常情况下,建议使用str作为dictkey