前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python 的几种数据类型

python 的几种数据类型

作者头像
xindoo
发布2021-01-22 12:43:25
1.5K0
发布2021-01-22 12:43:25
举报
文章被收录于专栏:XINDOO的专栏XINDOO的专栏

列表 列表是 Python 的主力数据类型。当提到 “ 列表 ” 时,您脑海中可 能会闪现“ 必须进一步声明大小的数组,只能包含同一类对象 “ 等想法。千万别这么想。列表比那要酷得多。 ☞ Python 中的列表类似 Perl 5 中的数组。在 Perl 5 中,存储数组的变量总是以字符 @ 开头;在 Python 中,变量可随意命名,Python 仅在内部对数据类型 进行跟踪。 ☞ Python 中的列表更像 Java 中的数组(尽管可以 把列表当做生命中所需要的一切来使用)。一个更好 的比喻可能是 ArrayList 类,该类可以容纳任何对 象,并可在添加新元素时进行动态拓展。 创建列表 列表创建非常轻松:使用中括号包裹一系列以逗号分割的值即 可。 >>> a_list = ['a', 'b', 'mpilgrim', 'z', 'example'] ① >>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] >>> a_list[0] ② 'a' >>> a_list[4] ③ 'example' >>> a_list[ ‐1] ④ 'example' >>> a_list[ ‐3] ⑤ 'mpilgrim' 1. 首先,创建一个包含 5 个元素的列表。要注意的是它们保持 了最初的顺序。这并不是偶然的。列表是元素的有序集合。 2. 列表可当做以零为基点的数组使用。非空列表的首个元素始 终是 a_list[0] 。 3. 该 5 元素列表的最后一个元素是 a_list[4] ,因为列表(索 引)总是以零为基点的。 4. 使用负索引值可从列表的尾部向前计数访问元素。任何非空 列表的最后一个元素总是 a_list[ ‐1] 。 5. 如果负数令你混淆,可将其视为如下方式: a_list[ ‐n] == a_list[len(a_list) ‐ n] 。因此在此列表中, a_list[ ‐3] == a_list[5 ‐ 3] == a_list[2] 。 列表切片 a_list[0] 是列表的第一个元素。 定义列表后,可从其中获取任何部分作为新列表。该技术称为 对列表进行 切片 。 >>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] >>> a_list[1:3] ① ['b', 'mpilgrim'] >>> a_list[1: ‐1] ② ['b', 'mpilgrim', 'z'] >>> a_list[0:3] ③ ['a', 'b', 'mpilgrim'] >>> a_list[:3] ④ ['a', 'b', 'mpilgrim'] >>> a_list[3:] ⑤ ['z', 'example'] >>> a_list[:] ⑥ ['a', 'b', 'mpilgrim', 'z', 'example'] 1. 通过指定两个索引值,可以从列表中获取称作“ 切片” 的某个 部分。返回值是一个新列表,它包含列表(??切片)中所有元素, 按顺序从第一个切片索引开始(本例中为 a_list[1] ),截止但 不包含第二个切片索引(本例中的 a_list[3] )。 2. 如果切片索引之一或两者均为负数,切片操作仍可进行。如 果有帮助的话,您可以这么思考:自左向右读取列表,第一个 切片索引指明了想要的第一个元素,第二个切片索引指明了第 一个不想要的元素。返回值是两者之间的任何值。 between. 3. 列表是以零为起点的,因此 a_list[0:3] 返回列表的头三个 元素,从 a_list[0] 开始,截止到但不包括 a_list[3] 。 4. 如果左切片索引为零,可以将其留空而将零隐去。因此 a_list[:3] 与 a_list[0:3] 是完全相同的,因为起点 0 被隐去 了。 5. 同样,如果右切片索引为列表的长度,也可以将其留空。因 此 a_list[3:] 与 a_list[3:5] 是完全相同的,因为该列表有五 个元素。此处有个好玩的对称现象。在这个五元素列表中, a_list[:3] 返回头三个元素,而 a_list[3:] 返回最后两个元 素。事实上,无论列表的长度是多少, a_list[:n] 将返回头 n 个 元素,而 a_list[ n:] 返回其余部分。 6. 如果两个切片索引都留空,那么将包括列表所有的元素。但 该返回值与最初的 a_list 变量并不一样。它是一个新列表,只 不过恰好拥有完全相同的元素而已。a_list[:] 是对列表进行复 制的一条捷径。 向列表中新增项 有四种方法可用于向列表中增加元素。 >>> a_list = ['a'] >>> a_list = a_list + [2.0, 3] ① >>> a_list ② ['a', 2.0, 3] >>> a_list.append(True) ③ >>> a_list ['a', 2.0, 3, True] >>> a_list.extend(['four', 'Ω']) ④ >>> a_list ['a', 2.0, 3, True, 'four', 'Ω'] >>> a_list.insert(0, 'Ω') ⑤ >>> a_list ['Ω', 'a', 2.0, 3, True, 'four', 'Ω'] 1. + 运算符连接列表以创建一个新列表。列表可包含任何数量 的元素;没有大小限制(除了可用内存的限制)。然而,如果 内存是个问题,那就必须知道在进行连接操作时,将在内存中 创建第二个列表。在该情况下,新列表将会立即被赋值给已有 变量 a_list 。因此,实际上该行代码包含两个步骤 — 连接然后 赋值 — 当处理大型列表时,该操作可能(暂时)消耗大量内 存。 2. 列表可包含任何数据类型的元素,单个列表中的元素无须全 为同一类型。下面的列表中包含一个字符串、一个浮点数和一 个整数。 3. append() 方法向列表的尾部添加一个新的元素。(现在列表 中有 四种 不同数据类型!) 4. 列表是以类的形式实现的。“ 创建” 列表实际上是将一个类实 例化。因此,列表有多种方法可以操作。extend() 方法只接受 一个列表作为参数,并将该参数的每个元素都添加到原有的列 表中。 5. insert() 方法将单个元素插入到列表中。第一个参数是列表 中将被顶离原位的第一个元素的位置索引。列表中的元素并不 一定要是唯一的;比如说:现有两个各自独立的元素,其值均 为 'Ω':,第一个元素 a_list[0] 以及最后一个元素 a_list[6] 。 ☞a_list.insert(0, value ) 就像是 Perl 中的 unshift() 函数。它将一个元素添加到列表的头 部,所有其它的元素都被顶理原先的位置以腾出空 间。 让我们进一步看看 append() 和 extend() 的区别。 >>> a_list = ['a', 'b', 'c'] >>> a_list.extend(['d', 'e', 'f']) ① >>> a_list ['a', 'b', 'c', 'd', 'e', 'f'] >>> len(a_list) ② 6 >>> a_list[ ‐1] 'f' >>> a_list.append(['g', 'h', 'i']) ③ >>> a_list ['a', 'b', 'c', 'd', 'e', 'f', ['g', 'h', 'i']] >>> len(a_list) ④ 7 >>> a_list[ ‐1] ['g', 'h', 'i'] 1. extend() 方法只接受一个参数,而该参数总是一个列表,并 将列表 a_list 中所有的元素都添加到该列表中。 2. 如果开始有个 3 元素列表,然后将它与另一个 3 元素列表进 行 extend 操作,结果是将获得一个 6 元素列表。 3. 另一方面, append() 方法只接受一个参数,但可以是任何数 据类型。在此,对一个 3 元素列表调用 append() 方法。 4. 如果开始的时候有个 6 元素列表,然后将一个列表 append [添加]上去,结果就会……得到一个 7 元素列表。为什么是 7 个?因为最后一个元素(刚刚 append[添加] 的元素) 本身 是个列表 。列表可包含任何类型的数据,包括其它列表。这可 能是你所需要的结果,也许不是。但如果这就是你想要的,那 这就是你所得到的。 在列表中检索值 >>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new'] >>> a_list.count('new') ① 2 >>> 'new' in a_list ② True >>> 'c' in a_list False >>> a_list.index('mpilgrim') ③ 3 >>> a_list.index('new') ④ 2 >>> a_list.index('c') ⑤ Traceback (innermost last): File "<interactive input>", line 1, in ?ValueError: list.index(x): x not in list 1. 如你所期望, count() 方法返回了列表中某个特定值出现的 次数。 2. 如果你想知道的是某个值是否出现在列表中, in 运算符将会 比使用 count() 方法要略快一些。in 运算符总是返回 True 或 False ;它不会告诉你该值出现在什么位置。 3. 如果想知道某个值在列表中的精确位置,可调用 index() 方 法。尽管可以通过第二个参数(以 0 为基点的)索引值来指定 起点,通过第三个参数(以 0 基点的)索引来指定搜索终点, 但缺省情况下它将搜索整个列表, 4. index() 方法将查找某值在列表中的第一次出现。在该情况 下,'new' 在列表中出现了两次,分别为 a_list[2] 和 a_list[4] ,但 index() 方法将只返回第一次出现的位置索引 值。 5. 可能 出乎 您的预期,如果在列表中没有找到该值,index() 方法将会引发一个例外。 等等,什么?是这样的:如果没有在列表中找到该值, index() 方法将会引发一个例外。这是 Python 语言最显著不同之处,其 它多数语言将会返回一些无效的索引值(像是 ‐1)。当然,一 开始这一点看起来比较讨厌,但我想您会逐渐欣赏它。这意味 着您的程序将会在问题的源头处崩溃,而不是之后奇怪地、默 默地崩溃。请记住, ‐1 是合法的列表索引值。如果 index() 方 法返回 ‐1,可能会导致调整过程变得不那么有趣! 从列表中删除元素 列表永远不会有缝隙。 列表可以自动拓展或者收缩。您已经看到了拓展部分。也有几 种方法可从列表中删除元素。 >>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new'] >>> a_list[1] 'b' >>> del a_list[1] ① >>> a_list ['a', 'new', 'mpilgrim', 'new'] >>> a_list[1] ② 'new' 1. 可使用 del 语句从列表中删除某个特定元素。 2. 删除索引 1 之后再访问索引 1 将 不会 导致错误。被删除元素 之后的所有元素将移动它们的位置以“ 填补” 被删除元素所产生 的“ 缝隙” 。 不知道位置索引?这不成问题,您可以通过值而不是索引删除 元素。 >>> a_list.remove('new') ① >>> a_list ['a', 'mpilgrim', 'new'] >>> a_list.remove('new') ② >>> a_list ['a', 'mpilgrim'] >>> a_list.remove('new') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: list.remove(x): x not in list 1. 还可以通过 remove() 方法从列表中删除某个元素。remove() 方法接受一个 value 参数,并删除列表中该值的第一次出现。同 样,被删除元素之后的所有元素将会将索引位置下移,以“ 填补 缝隙” 。列表永远不会有“ 缝隙” 。 2. 您可以尽情地调用 remove() 方法,但如果试图删除列表中不 存在的元素,它将引发一个例外。 R EMOVING I TEMS FROM A LIST : BONUS R OUND 另一有趣的列表方法是 pop() 。pop() 方法是从列表删除元素的 另一方法,但有点变化。 >>> a_list = ['a', 'b', 'new', 'mpilgrim'] >>> a_list.pop() ① 'mpilgrim' >>> a_list ['a', 'b', 'new'] >>> a_list.pop(1) ② 'b' >>> a_list ['a', 'new'] >>> a_list.pop() 'new' >>> a_list.pop() 'a' >>> a_list.pop() ③ Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: pop from empty list 1. 如果不带参数调用, pop() 列表方法将删除列表中最后的元 素,并返回所删除的值。 2. 可以从列表中 pop [弹出]任何元素。只需传给 pop() 方法 一个位置索引值。它将删除该元素,将其后所有元素移位以“ 填 补缝隙”, 然后返回它删除的值。 3. 对空列表调用 pop() 将会引发一个例外。 ☞不带参数调用的 pop() 列表方法就像 Perl 中的 pop() 函数。它从列表中删除最后一个元素并返回 所删除元素的值。Perl 还有另一个函数 shift() , 可用于删除第一个元素并返回其值;在 Python 中,该函数相当于 a_list.pop(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']) ② yes, it's true >>> is_it_true([False]) ③ yes, it's true 1. 在布尔类型上下文环境中,空列表为假值。 2. 任何至少包含一个上元素的列表为真值。 3. 任何至少包含一个上元素的列表为真值。元素的值无关紧 要。 ⁂ 元组 元素 是不可变的列表。一旦创建之后,用任何方法都不可以修 改元素。 >>> a_tuple = ("a", "b", "mpilgrim", "z", "example") ① >>> a_tuple ('a', 'b', 'mpilgrim', 'z', 'example') >>> a_tuple[0] ② 'a' >>> a_tuple[‐1] ③ 'example' >>> a_tuple[1:3] ④ ('b', 'mpilgrim') 1. 元组的定义方式和列表相同,除了整个元素的集合都用圆括 号,而不是方括号闭合。 2. 和列表一样,元组的元素都有确定的顺序。元组的索引也是 以零为基点的,和列表一样,因此非空元组的第一个元素总是 a_tuple[0] 。 3. 负的索引从元组的尾部开始计数,这和列表也是一样的。 4. 和列表一样,元组也可以进行切片操作。对列表切片可以得 到新的列表;对元组切片可以得到新的元组。 元组和列表的主要区别是元组不能进行修改。用技术术语来 说,元组是 不可变更 的。从实践的角度来说,没有可用于修改 元组的方法。列表有像 append()、 extend()、 insert()、 remove() 和 pop() 这样的方法。这些方法,元组都没有。可以 对元组进行切片操作(因为该方法创建一个新的元组),可以 检查元组是否包含了特定的值(因为该操作不修改元组),还 可以……就那么多了。 # continued from the previous example >>> a_tuple ('a', 'b', 'mpilgrim', 'z', 'example') >>> a_tuple.append("new") ① Traceback (innermost last): File "<interactive input>", line 1, in ?AttributeError: 'tuple' object has no attribute 'append' >>> a_tuple.remove("z") ② Traceback (innermost last): File "<interactive input>", line 1, in ?AttributeError: 'tuple' object has no attribute 'remove' >>> a_tuple.index("example") ③ 4 >>> "z" in a_tuple ④ True 1. 无法向元组添加元素。元组没有 append() 或 extend() 方 法。 2. 不能从元组中删除元素。元组没有 remove() 或 pop() 方法。 3. 可以 在元组中查找元素,由于该操作不改变元组。 4. 还可以使用 in 运算符检查某元素是否存在于元组中。 那么元组有什么好处呢? • 元组的速度比列表更快。如果定义了一系列常量值,而所需 做的仅是对它进行遍历,那么请使用元组替代列表。 • 对不需要改变的数据进行“ 写保护” 将使得代码更加安全。使 用元组替代列表就像是有一条隐含的 assert 语句显示该数据是 常量,特别的想法(及特别的功能)必须重写。(??) • 一些元组可用作字典键(特别是包含字符串、数值和其它元 组这样的不可变数据的元组)。列表永远不能当做字典键使 用,因为列表不是不可变的。 ☞元组可转换成列表,反之亦然。内建 的 tuple() 函数接受一个列表参数,并返回 一个包含同样元素的元组,而 list() 函数 接受一个元组参数并返回一个列表。从效 果上看, tuple() 冻结列表,而 list() 融 化元组。 布尔上下文环境中的元组 可以在 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', 'b')) ② yes, it's true >>> is_it_true((False,)) ③ yes, it's true >>> type((False)) ④ <class 'bool'> >>> type((False,)) <class 'tuple'> 1. 在布尔类型上下文环境中,空元组为假值。 2. 任何至少包含一个上元素的元组为真值。 3. 任何至少包含一个上元素的元组为真值。元素的值无关紧 要。不过此处的逗号起什么作用呢? 4. 为创建单元素元组,需要在值之后加上一个逗号。没有逗 号,Python 会假定这只是一对额外的圆括号,虽然没有害处, 但并不创建元组。 同时赋多个值 以下是一种很酷的编程捷径:在 Python 中,可使用元组来一次 赋多值。 >>> v = ('a', 2, True) >>> (x, y, z) = v ① >>> x 'a' >>> y 2 >>> z True 1. v 是一个三元素的元组,而 (x, y, z) 是包含三个变量的元 组。将其中一个赋值给另一个将会把 v 中的每个值按顺序赋值 给每一个变量。 该特性有多种用途。假设需要将某个名称指定某个特定范围的 值。可以使用内建的 range() 函数进行多变量赋值以快速地进 行连续变量赋值。 >>> (MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7) ① >>> MONDAY ② 0 >>> TUESDAY 1 >>> SUNDAY 6 1. 内建的 range() 函数构造了一个整数序列。(从技术上来 说, range() 函数返回的既不是列表也不是元组,而是一个 迭 代器,但稍后您将学到它们的区别。) MONDAY、 TUESDAY 、 WEDNESDAY 、 THURSDAY、 FRIDAY、 SATURDAY 和 SUNDAY 是您所定 义的变量。(本例来自于 calendar 模块,该短小而有趣的模块 打印日历,有点像 UNIX 程序 cal 。该 calendar 模块为星期数 定义了整数常量。 2. 现在,每个变量都有其值了: MONDAY 为 0 , TUESDAY 为 1, 如此类推。 还可以使用多变量赋值创建返回多值的函数,只需返回一个包 含所有值的元组。调用者可将返回值视为一个简单的元组,或 将其赋值给不同的变量。许多标准 Python 类库这么干,包括在 下一章将学到的 os 模块。 ⁂ 集合 集合set 是装有独特值的无序“ 袋子” 。一个简单的集合可以包含 任何数据类型的值。如果有两个集合,则可以执行像联合、交 集以及集合求差等标准集合运算。 创建集合 重中之重。创建集合非常简单。 >>> a_set = {1} ① >>> a_set {1} >>> type(a_set) ② <class 'set'> >>> a_set = {1, 2} ③ >>> a_set {1, 2} 1. 要创建只包含一个值的集合,仅需将该值放置于花括号之 间。({})。 2. 实际上,集合以 类 的形式实现,但目前还无须考虑这一点。 3. 要创建多值集合,请将值用逗号分开,并用花括号将所有值 包裹起来。 还可以 列表 为基础创建集合。 >>> 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] 1. 要从列表创建集合,可使用 set() 函数。(懂得如何实现集 合的学究可能指出这实际上并不是调用某个函数,而是对某个 类进行实例化。我保证在本书稍后的地方将会学到其中的区 别。目前而言,仅需知道 set() 行为与函数类似,以及它返回 一个集合。) 2. 正如我之前提到的,简单的集合可以包括任何数据类型的 值。而且,如我之前所提到的,集合是 无序的。该集合并不记 得用于创建它的列表中元素的最初顺序。如果向集合中添加元 素,它也不会记得添加的顺序。 3. 初始的列表并不会发生变化。 还没有任何值?没有问题。可以创建一个空的集合。 >>> a_set = set() ① >>> a_set ② set() >>> type(a_set) ③ <class 'set'> >>> len(a_set) ④ 0 >>> not_sure = {} ⑤ >>> type(not_sure) <class 'dict'> 1. 要创建空集合,可不带参数调用 set() 。 2. 打印出来的空集合表现形式看起来有点儿怪。也许,您期望 看到一个 {} 吧 ?该符号表示一个空的字典,而不是一个空的集 合。本章稍后您将学到关于字典的内容。 3. 尽管打印出的形式奇怪,这 确实是 一个集合…… 4. …… 同时该集合没有任何成员。 5. 由于从 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 1. add() 方法接受单个可以是任何数据类型的参数,并将该值 添加到集合之中。 2. 该集合现在有三个成员了。 3. 集合是装 唯一值 的袋子。如果试图添加一个集合中已有的 值,将不会发生任何事情。将不会引发一个错误;只是一条空 操作。 4. 该集合 仍然 只有三个成员。 >>> 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} 1. update() 方法仅接受一个集合作为参数,并将其所有成员添 加到初始列表中。其行为方式就像是对参数集合中的每个成员 调用 add() 方法。 2. 由于集合不能包含重复的值,因此重复的值将会被忽略。 3. 实际上,可以带任何数量的参数调用 update() 方法。如果调 用时传递了两个集合, update() 将会被每个集合中的每个成员 添加到初始的集合当中(丢弃重复值)。 4. 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 "<stdin>", line 1, in <module> KeyError: 21 1. discard() 接受一个单值作为参数,并从集合中删除该值。 2. 如果针对一个集合中不存在的值调用 discard() 方法,它不 进行任何操作。不产生错误;只是一条空指令。 3. remove() 方法也接受一个单值作为参数,也从集合中将其删 除。 4. 区别在这里:如果该值不在集合中,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 "<stdin>", line 1, in <module> KeyError: 'pop from an empty set' 1. pop() 方法从集合中删除某个值,并返回该值。然而,由于 集合是无序的,并没有“ 最后一个” 值的概念,因此无法控制删 除的是哪一个值。它基本上是随机的。 2. clear() 方法删除集合中 所有 的值,留下一个空集合。它等 价于 a_set = set() ,该语句创建一个新的空集合,并用之覆盖 a_set 变量的之前的值。 3. 试图从空集合中弹出某值将会引发 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} 1. 要检测某值是否是集合的成员,可使用 in 运算符。其工作原 理和列表的一样。 2. union() 方法返回一个新集合,其中装着 在两个 集合中出现 的元素。 3. intersection() 方法返回一个新集合,其中装着 同时 在两个 集合中出现的所有元素。 4. difference() 方法返回的新集合中,装着所有在 a_set 出现 但未在 b_set 中的元素。 5. 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 1. a_set 与 b_set 的对称差分 看起来 和b_set 与 a_set 的对称 差分不同,但请记住:集合是无序的。任何两个包含所有同样 值(无一遗漏)的集合可认为是相等的。 2. 而这正是这里发生的事情。不要被 Python Shell 对这些集合 的输出形式所愚弄了。它们包含相同的值,因此是相等的。 3. 对两个集合的 Union[并集]操作也是对称的。 4. 对两个集合的 Intersection [交集]操作也是对称的。 5. 对两个集合的 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 1. a_set 是 b_set 的 子集 — 所有 a_set 的成员均为 b_set 的成 员。 2. 同样的问题反过来说, b_set 是 a_set 的 超集,因为 a_set 的所有成员均为 b_set 的成员。 3. 一旦向 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 1. 在布尔类型上下文环境中,空集合为假值。 2. 任何至少包含一个上元素的集合为真值。 3. 任何至少包含一个上元素的集合为真值。元素的值无关紧 要。 ⁂ 字典 字典 是键值对的无序集合。向字典添加一个键的同时,必须为 该键增添一个值。(之后可随时修改该值。) 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 "<stdin>", line 1, in <module> KeyError: 'db.diveintopython3.org' 1. 首先,通过将两个字典项指定给 a_dict 变量创建了一个新字 典。每个字典项都是一组键值对,整个字典项集合都被大括号 包裹在内。 2. 'server' 为键,通过 a_dict['server'] 引用的关联值为 'db.diveintopython3.org' 。 3. 'database' 为键,通过 a_dict['database'] 引用的关联值为 'mysql' 。 4. 可以通过键获取值,但不能通过值获取键。因此 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'} 1. 在字典中不允许有重复的键。对现有的键赋值将会覆盖旧 值。 2. 可随时添加新的键值对。该语法与修改现有值相同。 3. 新字典项(键为 'user',值为 'mark')出现在中间。事实 上,在第一个例子中字典项按顺序出现是个巧合;现在它们不 按顺序出现同样也是个巧合。 4. 对既有字典键进行赋值只会用新值替代旧值。 5. 该操作会将 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' 1. 类似 列表 和 集合 ,len() 函数将返回字典中键的数量。 2. 而且像列表和集合一样,可使用 in 运算符以测试某个特定的 键是否在字典中。 3. 1000 是 字典 SUFFIXES 的一个键;其值为一个 8 元素列表 (确切地说,是 8 个字符串)。 4. 同样, 1024 是字典 SUFFIXES 的键;其值也是一个 8 元素列 表。 5. 由于 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 1. 在布尔类型上下文环境中,空字典为假值。 2. 至少包含一个键值对的字典为真值。 ⁂ NONE None 是 Python 的一个特殊常量。它是一个 空 值。None 与 False 不同。None 不是 0 。None 不是空字符串。将 None 与任何 非 None 的东西进行比较将总是返回 False 。 None 是唯一的空值。它有着自己的数据类型(NoneType)。可 将 None 赋值给任何变量,但不能创建其它 NoneType 对象。所 有值为 None 变量是相等的。 >>> type(None) <class 'NoneType'> >>> None == False False >>> None == 0 False >>> None == '' False >>> None == None True >>> x = None >>> x == None True >>> y = None >>> x == y True 布尔上下文环境中的 NONE 在 布尔类型上下文环境中, None 为假值,而 not None 为真 值。 >>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... >>> is_it_true(None) no, it's false >>> is_it_true(not None) yes, it's true

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2013-08-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档