python中集合和字典的使用

集合
集合set是装有独特值的无序“袋子”。一个简单的集合可以包含任何数据类型的值。如果有两个集合,则可以执行像联合、交集以及集合求差等标准集合运算。
创建集合
重中之重。创建集合非常简单。

>>> a_set = {1}①
>>> a_set

{1}

>>> type(a_set)

class “set”

>>> a_set = {1, 2}③
>>> a_set

{1, 2}
要创建只包含一个值的集合,仅需将该值放置于花括号之间。({})。
实际上,集合以 类 的形式实现,但目前还无须考虑这一点。
要创建多值集合,请将值用逗号分开,并用花括号将所有值包裹起来。

还可以 列表 为基础创建集合。

>>> a_list = ["a", "b", "mpilgrim", True, False, 42]
>>> a_set = set(a_list)①
>>> a_set

{“a”, False, “b”, True, “mpilgrim”, 42}

>>> a_list③

[“a”, “b”, “mpilgrim”, True, False, 42]
要从列表创建集合,可使用 set() 函数。(懂得如何实现集合的学究可能指出这实际上并不是调用某个函数,而是对某个类进行实例化。我保证在本书稍后的地方将会学到其中的区别。目前而言,仅需知道 set() 行为与函数类似,以及它返回一个集合。)
正如我之前提到的,简单的集合可以包括任何数据类型的值。而且,如我之前所提到的,集合是 无序的。该集合并不记得用于创建它的列表中元素的最初顺序。如果向集合中添加元素,它也不会记得添加的顺序。
初始的列表并不会发生变化。

还没有任何值?没有问题。可以创建一个空的集合。

>>> a_set = set()①
>>> a_set

set()

>>> type(a_set)

class “set”

>>> len(a_set)④

0

>>> not_sure = {}⑤
>>> type(not_sure)

class “dict”
要创建空集合,可不带参数调用 set() 。
打印出来的空集合表现形式看起来有点儿怪。也许,您期望看到一个 {} 吧 ?该符号表示一个空的字典,而不是一个空的集合。本章稍后您将学到关于字典的内容。
尽管打印出的形式奇怪,这 确实是 一个集合……
…… 同时该集合没有任何成员。
由于从 Python 2 沿袭而来历史的古怪规定,不能使用两个花括号来创建空集合。该操作实际创建一个空字典,而不是一个空集合。
修改集合
有两种方法可向现有集合中添加值: add() 方法和 update() 方法。

>>> a_set = {1, 2}
>>> a_set.add(4)①
>>> a_set

{1, 2, 4}

>>> len(a_set)②

3

>>> a_set.add(1)③
>>> a_set

{1, 2, 4}

>>> len(a_set)④

3
add() 方法接受单个可以是任何数据类型的参数,并将该值添加到集合之中。
该集合现在有三个成员了。
集合是装 唯一值 的袋子。如果试图添加一个集合中已有的值,将不会发生任何事情。将不会引发一个错误;只是一条空操作。
该集合 仍然 只有三个成员。

>>> a_set = {1, 2, 3}
>>> a_set

{1, 2, 3}

>>> a_set.update({2, 4, 6})①
>>> a_set②

{1, 2, 3, 4, 6}

>>> a_set.update({3, 6, 9}, {1, 2, 3, 5, 8, 13})③
>>> a_set

{1, 2, 3, 4, 5, 6, 8, 9, 13}

>>> a_set.update([10, 20, 30])④
>>> a_set

{1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 20, 30}
update() 方法仅接受一个集合作为参数,并将其所有成员添加到初始列表中。其行为方式就像是对参数集合中的每个成员调用 add() 方法。
由于集合不能包含重复的值,因此重复的值将会被忽略。
实际上,可以带任何数量的参数调用 update() 方法。如果调用时传递了两个集合, update() 将会被每个集合中的每个成员添加到初始的集合当中(丢弃重复值)。
update() 方法还可接受一些其它数据类型的对象作为参数,包括列表。如果调用时传入列表,update() 将会把列表中所有的元素添加到初始集合中。
从集合中删除元素
有三种方法可以用来从集合中删除某个值。前两种,discard() 和 remove() 有细微的差异。

>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}
>>> a_set

{1, 3, 36, 6, 10, 45, 15, 21, 28}

>>> a_set.discard(10)①
>>> a_set

{1, 3, 36, 6, 45, 15, 21, 28}

>>> a_set.discard(10)②
>>> a_set

{1, 3, 36, 6, 45, 15, 21, 28}

>>> a_set.remove(21)③
>>> a_set

{1, 3, 36, 6, 45, 15, 28}

>>> a_set.remove(21)④

Traceback (most recent call last): File “”, line 1, in KeyError: 21
discard() 接受一个单值作为参数,并从集合中删除该值。
如果针对一个集合中不存在的值调用 discard() 方法,它不进行任何操作。不产生错误;只是一条空指令。
remove() 方法也接受一个单值作为参数,也从集合中将其删除。
区别在这里:如果该值不在集合中,remove() 方法引发一个 KeyError 例外。

就像列表,集合也有个 pop() 方法。

>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}
>>> a_set.pop()①

1

>>> a_set.pop()

3

>>> a_set.pop()

36

>>> a_set

{6, 10, 45, 15, 21, 28}

>>> a_set.clear()②
>>> a_set

set()

>>> a_set.pop()③

Traceback (most recent call last): File “”, line 1, in KeyError: “pop from an empty set”
pop() 方法从集合中删除某个值,并返回该值。然而,由于集合是无序的,并没有“最后一个”值的概念,因此无法控制删除的是哪一个值。它基本上是随机的。
clear() 方法删除集合中 所有 的值,留下一个空集合。它等价于 a_set = set(),该语句创建一个新的空集合,并用之覆盖a_set变量的之前的值。
试图从空集合中弹出某值将会引发 KeyError 例外。
常见集合操作
Python 的 集合 类型支持几种常见的运算。

>>> a_set = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195}
>>> 30 in a_set

True

>>> 31 in a_set

False

>>> b_set = {1, 2, 3, 5, 6, 8, 9, 12, 15, 17, 18, 21}
>>> a_set.union(b_set)②

{1, 2, 195, 4, 5, 6, 8, 12, 76, 15, 17, 18, 3, 21, 30, 51, 9, 127}

>>> a_set.intersection(b_set)③

{9, 2, 12, 5, 21}

>>> a_set.difference(b_set)④

{195, 4, 76, 51, 30, 127}

>>> a_set.symmetric_difference(b_set)⑤

{1, 3, 4, 6, 8, 76, 15, 17, 18, 195, 127, 30, 51}
要检测某值是否是集合的成员,可使用 in 运算符。其工作原理和列表的一样。
union() 方法返回一个新集合,其中装着 在两个 集合中出现的元素。
intersection() 方法返回一个新集合,其中装着 同时 在两个集合中出现的所有元素。
difference() 方法返回的新集合中,装着所有在a_set出现但未在b_set中的元素。
symmetric_difference() 方法返回一个新集合,其中装着所有 只在其中一个 集合中出现的元素。

这三种方法是对称的。

continued from the previous example

>>> b_set.symmetric_difference(a_set)①

{3, 1, 195, 4, 6, 8, 76, 15, 17, 18, 51, 30, 127}

>>> b_set.symmetric_difference(a_set) == a_set.symmetric_difference(b_set)②

True

>>> b_set.union(a_set) == a_set.union(b_set)③

True

>>> b_set.intersection(a_set) == a_set.intersection(b_set)④

True

>>> b_set.difference(a_set) == a_set.difference(b_set)⑤

False
a_set与b_set的对称差分 看起来 和b_set与a_set的对称差分不同,但请记住:集合是无序的。任何两个包含所有同样值(无一遗漏)的集合可认为是相等的。
而这正是这里发生的事情。不要被 Python Shell 对这些集合的输出形式所愚弄了。它们包含相同的值,因此是相等的。
对两个集合的 Union[并集]操作也是对称的。
对两个集合的 Intersection[交集]操作也是对称的。
对两个集合的 Difference[求差]操作不是对称的。这是有意义的;它类似于从一个数中减去另一个数。操作数的顺序会导致结果不同。

最后,有几个您可能会问到的问题。

>>> a_set = {1, 2, 3}
>>> b_set = {1, 2, 3, 4}
>>> a_set.issubset(b_set)①

True

>>> b_set.issuperset(a_set)②

True

>>> a_set.add(5)③
>>> a_set.issubset(b_set)

False

>>> b_set.issuperset(a_set)

False
a_set是b_set的子集— 所有a_set的成员均为b_set的成员。
同样的问题反过来说,b_set是a_set的超集,因为a_set的所有成员均为b_set的成员。
一旦向a_set添加一个未在b_set中出现的值,两项测试均返回 False 。
布尔上下文环境中的集合
可在 if 这样的 布尔类型上下文环境中 使用集合。

>>> def is_it_true(anything):

… if anything:
… print(“yes, it”s true”)
… else:
… print(“no, it”s false”)

>>> is_it_true(set())①

no, it”s false

>>> is_it_true({"a"})②

yes, it”s true

>>> is_it_true({False})③

yes, it”s true
在布尔类型上下文环境中,空集合为假值。
任何至少包含一个上元素的集合为真值。
任何至少包含一个上元素的集合为真值。元素的值无关紧要。

字典
字典是键值对的无序集合。向字典添加一个键的同时,必须为该键增添一个值。(之后可随时修改该值。) Python 的字典为通过键获取值进行了优化,而不是反过来。
☞Python 中的字典与 Perl 5 中的 hash [散列]类似。在 Perl 5 中,散列存储的变量总是以一个 % 符开头。在 Python 中,变量可以随意命名,而 Python 内部跟踪其数据类型。
创建字典
创建字典非常简单。其语法与 集合 的类似,但应当指定键值对而不是值。有了字典后,可以通过键来查找值。

>>> a_dict = {"server": "db.diveintopython3.org", "database": "mysql"}①
>>> a_dict

{“server”: “db.diveintopython3.org”, “database”: “mysql”}

>>> a_dict["server"]②

“db.diveintopython3.org”

>>> a_dict["database"]③

“mysql”

>>> a_dict["db.diveintopython3.org"]④

Traceback (most recent call last): File “”, line 1, in KeyError: “db.diveintopython3.org”
首先,通过将两个字典项指定给a_dict变量创建了一个新字典。每个字典项都是一组键值对,整个字典项集合都被大括号包裹在内。
“server” 为键,通过 a_dict[“server”] 引用的关联值为 “db.diveintopython3.org” 。
“database” 为键,通过 a_dict[“database”] 引用的关联值为 “mysql” 。
可以通过键获取值,但不能通过值获取键。因此 a_dict[“server”] 为 “db.diveintopython3.org”,而 a_dict[“db.diveintopython3.org”] 会引发例外,因为 “db.diveintopython3.org” 并不是键。
修改字典
字典没有预定义的大小限制。可以随时向字典中添加新的键值对,或者修改现有键所关联的值。继续前面的例子:

>>> a_dict

{“server”: “db.diveintopython3.org”, “database”: “mysql”}

>>> a_dict["database"] = "blog">>> a_dict

{“server”: “db.diveintopython3.org”, “database”: “blog”}

>>> a_dict["user"] = "mark">>> a_dict③

{“server”: “db.diveintopython3.org”, “user”: “mark”, “database”: “blog”}

>>> a_dict["user"] = "dora">>> a_dict

{“server”: “db.diveintopython3.org”, “user”: “dora”, “database”: “blog”}

>>> a_dict["User"] = "mark">>> a_dict

{“User”: “mark”, “server”: “db.diveintopython3.org”, “user”: “dora”, “database”: “blog”}
在字典中不允许有重复的键。对现有的键赋值将会覆盖旧值。
可随时添加新的键值对。该语法与修改现有值相同。
新字典项(键为 “user”,值为 “mark”)出现在中间。事实上,在第一个例子中字典项按顺序出现是个巧合;现在它们不按顺序出现同样也是个巧合。
对既有字典键进行赋值只会用新值替代旧值。
该操作会将 user 键的值改回 “mark” 吗?不会!仔细看看该键——有个大写的U出现在”User”中。字典键是区分大小写的,因此该语句创建了一组新的键值对,而不是覆盖既有的字典项。对你来说它们可能是一样的,但对于 Python 而言它们是完全不同的。
混合值字典

典并非只能用于字符串。字典的值可以是任何数据类型,包括整数、布尔值、任何对象,甚至是其它的字典。而且就算在同一字典中,所有的值也无须是同一类型,
您可根据需要混合匹配。字典的键要严格得多,可以是字符串、整数和其它一些类型。在同一字典中也可混合、匹配使用不同数据类型的键。
实际上,您已经在 your first Python program 见过一个将非字符串用作键的字典了。
SUFFIXES = {1000: [“KB”, “MB”, “GB”, “TB”, “PB”, “EB”, “ZB”, “YB”],
1024: [“KiB”, “MiB”, “GiB”, “TiB”, “PiB”, “EiB”, “ZiB”, “YiB”]}

让我们在交互式 shell 中剖析一下:

>>> SUFFIXES = {1000: ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"],

… 1024: [“KiB”, “MiB”, “GiB”, “TiB”, “PiB”, “EiB”, “ZiB”, “YiB”]}

>>> len(SUFFIXES)①

2

>>> 1000 in SUFFIXES②

True

>>> SUFFIXES[1000]

[“KB”, “MB”, “GB”, “TB”, “PB”, “EB”, “ZB”, “YB”]

>>> SUFFIXES[1024]

[“KiB”, “MiB”, “GiB”, “TiB”, “PiB”, “EiB”, “ZiB”, “YiB”]

>>> SUFFIXES[1000][3]⑤

“TB”
类似 列表 和 集合 ,len() 函数将返回字典中键的数量。
而且像列表和集合一样,可使用 in 运算符以测试某个特定的键是否在字典中。
1000 是 字典 SUFFIXES 的一个键;其值为一个 8 元素列表(确切地说,是 8 个字符串)。
同样, 1024 是字典 SUFFIXES 的键;其值也是一个 8 元素列表。
由于 SUFFIXES[1000] 是列表,可以通过它们的 0 基点索引来获取列表中的单个元素。
布尔上下文环境中的字典
空字典为假值;所有其它字典为真值。

可以在 if 这样的 布尔类型上下文环境中 使用字典。

>>> def is_it_true(anything):

… if anything:
… print(“yes, it”s true”)
… else:
… print(“no, it”s false”)

>>> is_it_true({})①

no, it”s false

>>> is_it_true({"a": 1})②

yes, it”s true
在布尔类型上下文环境中,空字典为假值。
至少包含一个键值对的字典为真值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值