字典、集合

字典是一种用来存放若干键值对的数据类型。

什么是键值对呢?键值对就是两个对象,其中一个是用来做定位的数据,叫做键(Key),另一个是要存放的数据,叫做值(Value)。在字典中,键值对作为一个整体被存放,我们可以通过键来快速获取到对应的值。

在 Python 中字典用花括号({})来表示,键值对以 键:值 的方式写入花括号中,有多个键值对时用逗号分隔。

{'010': 'beijing', '021': 'shanghai'} 便是一个字典,其中包含两个键值对

  • '010': 'beijing'
  • '021': 'shanghai'

使用时,我们可以通过 '010' 快速查询到其对应的值是 'beijing'。这就好比现实中的一本字典一样,通过拼音或偏旁来映射一个具体的字词,以此来实现字词的快速查找,而这个拼音或偏旁就相当于 Python 字典的键,而字词就相当于 Python 字典的值,它们在字典中是映射关系。

Python 字典中的键是有要求的,需要是不可变的类型,如元组、字符串、数字。而字典中的值可以是任意类型。字典本身是可变的,我们可以向其中添加、删除、修改键值对。

因为字典不是序列,更不是有序的,所有它没有列表那样的索引,也不能保证每个键值对的存放次序。

创建字典

  • 1, 创建空的字典

    字典 = {}
    
    >>> empty_dict = {}
    >>> empty_dict
    {}
    
  • 2, 创建包含键值对的字典

    字典 = {键1:值1, 键2:值2, ..., 键N:值N}
    

    如城市和其对应的电话区号:

    >>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
    >>> codes
    {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
    

字典键值对的添加

向字典中增加键值对

字典[键] = 值
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes[‘tianjin’] = '022'
>>> codes
{‘beijing’: ‘010’, ‘shanghai’: ‘021’, ‘tianjin’: ‘022’}

使用这种方式时,若字典中没有这个键,则会创建这个键值对;若字典中原本已有这个键,则是修改键所对应的值。

键值对的获取

通过键获取值

值 = 字典[键]
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes[‘beijing’]
‘010

注意若键不存在则将抛出 KeyError 异常:

>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes[‘a’]
Traceback (most recent call last):
     File “”, line 1, in
KeyError: ‘a’

通过键获取值( get 方法)

如果通过键获取值时不希望 KeyError 异常抛出,可以使用 get 方法,若键不存在,则直接返回 None。

值 = 字典.get(键)
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes.get(‘a’)
>>>

返回的 None 代表什么都没有,所以没有任何值显示。

也可以给 get 方法传递第二个参数作为默认值,使得键不存在时直接返回默认值。

值 = 字典.get(键, 默认值)
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes.get(‘a’, ‘000’)
>>> 000

判断字典中是否包含某个键

布尔值 = 键 in 字典
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> ‘beijing’ in codes
True
>>> ‘guangzhou’ in codes
False

获取所有键

键的列表 = 字典.keys()
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes.keys()
dict_keys([‘beijing’, ‘shanghai’])

获取到的所有键是以迭代器的形式存在,至于什么是迭代器我们将在之后的章节中介绍。在这里我们可以用 list() 函数将迭代器转换为列表。如下:

>>> list(codes.keys())
[‘beijing’, ‘shanghai’]

获取所有值

值的列表 = 字典.values()
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes.values()
dict_values([‘010’, ‘021’])

获取到的所有值是以迭代器的形式存在,我们用 list() 函数将迭代器转换为列表。如下:

>>> list(codes.values())
[‘010’, ‘021’]

获取所有键值对的列表

值的列表 = 字典.items()
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes.items()
dict_items([(‘beijing’, ‘010’), (‘shanghai’, ‘021’)])

获取到的所有键值对是以迭代器的形式存在,我们用 list() 函数将迭代器转换为列表。如下:

>>> list(codes.items())
[(‘beijing’, ‘010’), (‘shanghai’, ‘021’)]

列表中的每一个元素是都是二元组(即包含两个元素的元组),每个二元组的第一个元素是键,第二个元素是值。

字典键值对的删除

通过键删除键值对

可以使用 pop 方法删除一个键值对,并将值返回。

值 = 字典.pop(键)
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes.pop(‘beijing’)
’010>>> codes
{‘shanghai’: ‘021’}

如果 pop 一个不存在的键,则会抛出 KeyError 异常:

>>> codes.pop(‘a’)
Traceback (most recent call last):
     File “”, line 1, in
KeyError: ‘a’

如果你不希望异常抛出,可以传递 pop方法的第二个参数作为默认值。默认值仅在键不存在时生效,此时方法将直接返回这个默认值,且跳过删除操作:

值 = 字典.pop(键, 默认值)
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes.pop(‘guangzhou’, ‘000’)
’000

通过键删除键值对(del 方法)

也可以通过关键字 del 来删除键值对。

del 字典[键]
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> del codes[‘beijing’]
>>> codes
{‘shanghai’: ‘021’}

随机删除一个键值对

使用 popitem 随机删除一个键值对,并返回这个键值对的二元组,二元组的第一个元素是键,第二个元素是值。

键值二元组 = 字典.popitem()
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes.popitem()
(‘shanghai’, ‘021’)
>>> codes
{‘beijing’: ‘010’}

清空所有键值对

键值二元组 = 字典.clear()
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes.clear()
>>> codes
{}

字典中键值对修改

修改键对应的值

字典[键] = 值
>>> codes = {‘beijing’: ‘010’}
>>> codes[‘beijing’] = '021'
>>> codes
{‘beijing’: ‘021’}

如果键不存在,则创建键值对。

用字典批量更新键值对

字典.update(另一字典)
>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> codes.update({‘guangzhou’: ‘020’, ‘shanghai’: ‘000’})
>>> codes
{‘beijing’: ‘010’, ‘shanghai’: ‘000’, ‘guangzhou’: ‘020’}

可以看到字典中新增了 'guangzhou': '020'这个键值对,同时将 'shanghai': '021' 修改为 'shanghai': '000'

什么时候用字典

字典的显著优势是可以通过键快速地查询数据。字典中的元素以键值对的形式存在,使用时通过键来获取和修改值,由于字典内部的特殊实现,字典通过键获取值的效率非常高。

如果我们希望将批量的数据存放起来,并且在需要时能以很高的执行效率来获取其中某个指定的数据,这时就可以使用字典。除此之外,如果我们想在程序中暂时维护一个映射关系,也可以使用字典,因为字典本质上就是一个映射关系。

如,我们可以将城市名和对应的区号保存在字典中,这样就可以通过城市名快速地查询到其区号,而不需要进行遍历。

area_codes = {
    '北京': '010',
    '上海': '021',
    '天津': '022',
    '重庆': '023',
    '沈阳': '024',
    '南京': '025',
    '武汉': '027',
    '成都': '028',
}
>>> area_codes[‘成都’]
‘028>>> area_codes[‘南京’]
‘025

集合

集合是一个用于存放批量元素的数据类型,它不是有序的,其中的元素没有顺序关系。集合中的元素没有重复,重复的元素将被自动剔除最终只留下一个。

集合也是用花括号({})来表示,不同于字典的是,花括号中放的是一个个数据,而不是键值对。

集合是可变的,我们可以向其中添加、删除、修改元素。

  • 1,创建集合

创建包含元素的集合

集合 = {元素1, 元素2, 元素N}
>>> numbers = {1, 2, 3}
>>> numbers
{1, 2, 3}
  • 2, 创建空集合
集合 = set()

注意创建空集合不能直接使用 {},那样是表示空字典,而是使用 set(),这才表示空集合。

>>> empty_set = set()
>>> empty_set
set()

集合元素的添加

向集合中添加一个元素

集合.add(元素)
>>> numbers = {1, 2}
>>> numbers.add(3)
>>> numbers
{1, 2, 3}

向集合中添加重复元素时,会被去重处理。

>>> numbers = {1, 2}
>>> numbers.add(2)
>>> numbers
{1, 2}

从另一集合中批量添加元素

集合.update(另一集合)
>>> numbers_1 = {1, 2}
>>> numbers_2 = {2, 3, 4}
>>> numbers_1.update(numbers_2)
>>> numbers_1
{1, 2, 3, 4}

可以看到,集合numbers_2 中的所有元素被添加到了集合 numbers_1中,并且其中重复的元素被剔除仅保留一份。

集合元素的获取

集合不能像列表那样通过索引来获取元素,也不能像字典那样通过键来获取值,集合没法直接获取到某个指定的元素。想要获取元素,只能通过遍历的方式。

虽然集合不能直接获取到元素,但是我们依然可以用 in 关键字来判断元素是否存在于集合中。

查看元素是否存在于集合中

布尔值 = 元素 in 集合
>>> letters = {‘a’, ‘b’, ‘c’}
>>> ‘a’ in letters
True
>>> ‘z’ in letters
False

集合元素的删除

随机删除一个元素,并返回这个元素

元素 = 集合.pop()

使用 pop 方法随机删除一个元素的时候,这个元素会被返回。

>>> numbers = {1, 2, 3}
>>> numbers.pop()
1
>>> numbers.pop()
2
>>> numbers
{3}

删除一个指定的元素

集合.remove(元素)
>>> numbers = {1, 2, 3}
>>> numbers.remove(1)
>>> numbers
{2, 3}

如果要删除的元素不存在,则抛出 KeyError 异常:

>>> numbers = {1, 2, 3}
>>> numbers.remove(4)
Traceback (most recent call last):
     File “”, line 1, in
KeyError: 4

删除一个指定的元素,且不抛出 KeyError 异常

使用 remove 方法删除一个不存在的元素时,会抛出 KeyError 异常,如果我们不想让异常抛出,可以使用 discard 方法。

集合.discard(元素)
>>> numbers = {1, 2, 3}
>>> numbers.discard(4)
>>> numbers
{1, 2, 3}

清空所有元素

集合.clear()

与列表和字典一样,想要清空所有元素,可以使用 clear 方法。

>>> numbers = {1, 2, 3}
>>> numbers.clear()
>>> numbers
set()

顺便考大家一个问题,为什么元组没有这个方法?因为元组是不可变的!我们不能删除元组的元素,也不能添加和修改元素。

集合的运算

看到这里你可能会想,集合不就是阉割版的列表嘛?不是的,集合的功能不止于此。

Python 中的集合和数学中的集合颇为相似,首先集合的所有元素都是唯一的,不存在重复;此外集合有子集、超集的概念,也可以进行交集、并集、差集的运算。

求交集

可以通过 intersection 方法求多个集合的交集。

交集 = 集合1.intersection(集合2, 集合3, 集合N)
>>> numbers_1 = {1, 2, 3}
>>> numbers_2 = {2, 3, 4}
>>> numbers_3 = {3, 4, 5}
>>> numbers_1.intersection(numbers_2, numbers_3)
{3}

也可以直接使用与运算符 &来代替,完全等效:

交集 = 集合1 & 集合2 & 集合N
>>> numbers_1 & numbers_2 & numbers_3
{3}

求并集

交集 = 集合1.union(集合2, 集合3, 集合N)
>>> numbers_1 = {1, 2, 3}
>>> numbers_2 = {2, 3, 4}
>>> numbers_3 = {3, 4, 5}
>>> numbers_1.union(numbers_2, numbers_3)
{1, 2, 3, 4, 5}

也可以直接使用或运算符 | 来代替,完全等效:

交集 = 集合1 | 集合2 | 集合N
>>> numbers_1 | numbers_2 | numbers_3
{1, 2, 3, 4, 5}

求差集

交集 = 集合1.difference(集合2, 集合3, 集合N)
>>> numbers_1 = {1, 2, 3}
>>> numbers_2 = {2, 3, 4}
>>> numbers_3 = {3, 4, 5}
>>> numbers_1.difference(numbers_2, numbers_3)
{1}

也可以直接使用运算符 -来代替,完全等效:

交集 = 集合1 - 集合2 - 集合N
>>> numbers_1 - numbers_2 - numbers_3
{1}

判断是否为子集

布尔值 = 集合1.issubset(集合2)

判断 集合1 是否为 集合2 的子集。

>>> numbers_1 = {2, 3}
>>> numbers_2 = {1, 2, 3}
>>> numbers_1.issubset(numbers_2)
True
>>> numbers_3 = {3, 4}
>>> numbers_1.issubset(numbers_3)
False

判断是否为超集

布尔值 = 集合1.issuperset(集合2)

判断 集合1 是否为 集合2 的子集。

>>> numbers_1 = {1, 2, 3}
>>> numbers_2 = {2, 3}
>>> numbers_1.issuperset(numbers_2)
True
>>> numbers_3 = {3, 4}
>>> numbers_1.issuperset(numbers_3)
False

集合运算示例

集合运算在编程时有什么用呢?以差集为例举个例子。

假如大学里有一个班,班里同学的花名册是「赵大,钱二,孙三,李四,周五,吴六,郑七,王八」。有一天上课,老师要求同学们在一张白纸上签到,大家陆续写上了自己的名字,上面有「周五,李四,王八,赵大,钱二,冯九,陈十」。哪些人缺席了呢?

要判断哪些人缺席了,通常的做法时,逐一从签到表上取出名字,然后去花名册上寻找并做标记,最终花名册上没被标记的名字便是缺席的。有些麻烦,这可苦了助教了。

我们可以用 Python 集合来快速解决这个问题。将花名册上的名字保存在集合中,将签到表上的名字保存在另一个集合中,然后求一下差集。如下:

>>> 花名册 = {‘赵大’, ‘钱二’, ‘孙三’, ‘李四’, ‘周五’, ‘吴六’, ‘郑七’, ‘王八’}
>>> 签到表 = {‘周五’, ‘李四’, ‘王八’, ‘赵大’, ‘钱二’, ‘冯九’, ‘陈十’}
>>> 花名册 - 签到表
{‘吴六’, ‘孙三’, ‘郑七’}

吴六,孙三,郑七没来!

我们用反过来用 签到表 - 花名册 看看:

>>> 签到表 - 花名册
{‘陈十’, ‘冯九’}

还有两个旁听生!

什么时候用集合?

集合非常重要的一个特性是元素无重复,每个元素都是唯一的,重复的元素将被自动剔除(去重)。

所以如果我们需要存放一系列的数据,并且不希望其中出现重复,那么就可以使用集合。

另外如果想计算两个数据集的交集、并集、差集,使用集合来承载数据再合适不过了,集合自带的集合运算能轻松解决这些问题。

获取字典和集合中的元素数量 我们可以通过 len() 函数来获取字典中的键值对数量和集合中的元素数量。

>>> codes = {‘beijing’: ‘010’, ‘shanghai’: ‘021’}
>>> len(codes)
2

>>> numbers = {1, 2, 3, 4}
>>> len(numbers)
4

总结

字典是一种用来存放若干键值对的数据类型,可通过键来快速查找值。

字典的键需要是不可变的类型,如数字,字符串和元组。字典的值可以是任意类型。字典本身是可变的,所以可向其中添加、修改、删除键值对。

集合是一个用于存放批量元素的序列。它不是有序的,且元素不会有重复。集合也是可变的,我们可以向其中添加、删除、修改元素。

results matching ""

    No results matching ""