RealPython 基础教程:Python 中的列表和元组
列表(list)和元组(tuple)几乎可称得上是 Python 中最常用、最有用的数据类型了。在每个非简单的 Python 中,你都能发现它们的使用之处。
本文将介绍 list 和 tuple 的重要特性。你将学会如何定义和使用它们,并掌握何时以及如何在 Python 程序中使用这些类型的对象。
【Python 中的列表(list)】
简言之,list 是一个包含任意对象的集合,有点像其他编程语言中的数组,但是更加灵活。
在 Python 中,使用中括号([])来定义一个包含一系列对象的 list,list 中的对象之间用逗号(,)隔开。
就像下边这样:
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> a
['foo', 'bar', 'baz', 'qux']
>>> type(a)
<class 'list'>
list 的重要特性包括:
list 是有序的
list 可以包含任意种类和数目的对象
list 支持使用索引来访问其中的元素
list 支持任意深度的嵌套
list 是可变的
list 是动态的
我们下边逐一详细介绍这些特性。
1,list 是有序的
list 不仅仅是对象的集合,它是这些对象的有序集合。定义 list 时为其中元素指定的顺序,是 list 的一个固有特征,并在 list 的整个生命周期中保持不变。
两个拥有相同元素但元素顺序不同的 list 是不相同的。
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> b = ['baz', 'qux', 'bar', 'foo']
>>> a == b
False
>>> a is b
False
>>>
>>> [1, 2, 3, 4] == [4, 1, 3, 2]
False
2,list 可以包含任意对象
list 可以包含各种各样的对象。
list 中的元素可以是相同类型的,也可以是不同类型的。
>>> a = [2, 4, 6, 8]
>>> a
[2, 4, 6, 8]
>>> a = [21.42, 'foobar', 3, 4, 'bark', False, 3.14159]
>>> a
[21.42, 'foobar', 3, 4, 'bark', False, 3.14159]
list 中也可以包含复杂的对象,比如函数、类以及模块。
>>> int
<class 'int'>
>>> len
<built-in function len>
>>> def foo():
... pass
...
>>> foo
<function foo at 0x000001D893CFFDC8>
>>> import math
>>> math
<module 'math' (built-in)>
>>>
>>> a = [int, len, foo, math]
>>> a
[<class 'int'>, <built-in function len>, <function foo at 0x000001D893CFFDC8>, <module 'math' (built-in)>]
list 可以包含任意数目的对象,从 0 个一直多到内存允许的最大值。
>>> a = []
>>> a
[]
>>> len(a)
0
>>> a = ['foo']
>>> a
['foo']
>>> len(a)
1
>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
>>> len(a)
21
list 中的对象不必是唯一的,一个对象可以在 list 中出现多次。
>>> a = ['bark', 'meow', 'woof', 'bark', 'cheep', 'bark']
>>> a
['bark', 'meow', 'woof', 'bark', 'cheep', 'bark']
3,可通过索引访问 list 中的元素
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[0]
'foo'
>>> a[2]
'baz'
>>> a[5]
'corge'
>>> a[-1]
'corge'
>>> a[-2]
'quux'
>>> a[-5]
'bar'
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[2:5]
['baz', 'qux', 'quux']
可使用正值或负值索引
>>> a[-5:-2]
['bar', 'baz', 'qux']
>>> a[1:4]
['bar', 'baz', 'qux']
>>> a[-5:-2] == a[1:4]
True
若忽略第一个索引,则切片起始于 list 的开头元素;若忽略第二个索引,则切片延伸至 list 的末尾元素
>>> print(a[:4], a[0:4])
['foo', 'bar', 'baz', 'qux'] ['foo', 'bar', 'baz', 'qux']
>>> print(a[2:], a[2:len(a)])
['baz', 'qux', 'quux', 'corge'] ['baz', 'qux', 'quux', 'corge']
>>>
>>> a[:4] + a[4:]
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[:4] + a[4:] == a
True
可指定切片的步长,步长可为正值或负值
>>> a[0:6:2]
['foo', 'baz', 'quux']
>>> a[1:6:2]
['bar', 'qux', 'corge']
>>> a[6:0:-2]
['corge', 'qux', 'bar']
反转 list 的方法和反转字符串的方法相同
>>> a[::-1]
['corge', 'quux', 'qux', 'baz', 'bar', 'foo']
[:] 语法适用于 list,但是这个操作在 list 和字符串的实现上有个重要的区别。
若 s 是一个字符串,s[:] 返回的是对字符串 s 的引用:
>>> s = 'foobar'
>>> s[:]
'foobar'
>>> s[:] is s
True
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[:]
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[:] is a
False
in 和 not in 运算符
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> 'qux' in a
True
>>> 'thud' not in a
True
连接(+)和复制(*)运算符
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a + ['grault', 'garply']
['foo', 'bar', 'baz', 'qux', 'quux', 'corge', 'grault', 'garply']
>>> a * 2
['foo', 'bar', 'baz', 'qux', 'quux', 'corge', 'foo', 'bar', 'baz', 'qux', 'quux', 'corge']
len()、min() 和 max() 函数
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> len(a)
6
>>> min(a)
'bar'
>>> max(a)
'qux'
>>> ['foo', 'bar', 'baz', 'qux', 'quux', 'corge'][2]
'baz'
>>> ['foo', 'bar', 'baz', 'qux', 'quux', 'corge'][::-1]
['corge', 'quux', 'qux', 'baz', 'bar', 'foo']
>>> 'quux' in ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
True
>>> ['foo', 'bar', 'baz'] + ['qux', 'quux', 'corge']
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> len(['foo', 'bar', 'baz', 'qux', 'quux', 'corge'][::-1])
6
4,list 可以嵌套
我们知道,list 中可以包含任意种类的对象,这其中就包括 list 类型的对象。
list 可以包含子 list,子 list 中还可以包含自己的子 list,如此这般,可以嵌套至任意深度。
看下边这个例子:
>>> x = ['a', ['bb', ['ccc', 'ddd'], 'ee', 'ff'], 'g', ['hh', 'ii'], 'j']
>>> x
['a', ['bb', ['ccc', 'ddd'], 'ee', 'ff'], 'g', ['hh', 'ii'], 'j']
x 指向的对象的结构可用下图表示:
x[0]、x[2] 和 x[4] 都是长度为 1 的字符串:
>>> print(x[0], x[2], x[4])
a g j
x[1] 和 x[3] 是 x 的子 list:
>>> x[1]
['bb', ['ccc', 'ddd'], 'ee', 'ff']
>>> x[3]
['hh', 'ii']
子 list 中的元素也可以通过索引语法来访问,只需要追加额外的 [] 包含的索引即可。
>>> x[1]
['bb', ['ccc', 'ddd'], 'ee', 'ff']
>>> x[1][0]
'bb'
>>> x[1][1]
['ccc', 'ddd']
>>> x[1][2]
'ee'
>>> x[1][3]
'ff'
>>>
>>> x[3]
['hh', 'ii']
>>> print(x[3][0], x[3][1])
hh ii
可以看到,x[1][1] 又是一个子 list,再增加一个索引就可以访问其中的元素:
>>> x[1][1]
['ccc', 'ddd']
>>> print(x[1][1][0], x[1][1][1])
ccc ddd
你可以定义任意嵌套深度的 list,当然,嵌套越深,访问起来也越复杂。
常见的索引和切片操作同样适用于子 list。
>>> x[1][1][-1]
'ddd'
>>> x[1][1:3]
[['ccc', 'ddd'], 'ee']
>>> x[3][::-1]
['ii', 'hh']
需要注意的是,list 上的运算符和函数操作仅作用在你指定的层级,它们不会递归应用在子 list 上。
我们以 len() 和 in 为例,看一下存在子 list 时的操作结果。
>>> x
['a', ['bb', ['ccc', 'ddd'], 'ee', 'ff'], 'g', ['hh', 'ii'], 'j']
>>> len(x)
5
>>>
>>> 'ddd' in x
False
>>> 'ddd' in x[1]
False
>>> 'ddd' in x[1][1]
True
len(x) 只返回 x 第一级的元素个数,不会包含子 list 中元素的数目;in 同样只判断 'ddd' 是否存在于右操作数所在的那一层级,不会在子 list 中递归查找。
5,list 是可变的
我们前边介绍的大部分数据类型都是原子类型。比如,整数或浮点数对象都是不可再分割的原始单元。这些类型是不可变的,意味着对象一旦被赋值就无法再次改变其内容。在 Python 中考虑改变一个整数的值没多大意义,如果你想要一个其他值的整数,再创建一个整数对象并为其赋值就行了。
和整数、浮点数有点不一样,字符串是一个复合类型。字符串可以被分拆为更小的部分:单个字符。看起来,修改字符串中某个字符的值是有意义的。但事实是,你无法改变字符串中单个字符的值。Python 中的字符串也是不可变的。
list 是我们遇到的第一个可变数据类型。list 对象创建之后,我们可向其中随意地添加、删除、变换和移动元素。Python 提供了很多方式用来修改 list。
5.1 修改 list 中单个元素的值
list 中单个元素的值可通过索引与简单赋值来替换。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[2] = 10
>>> a[-1] = 20
>>> a
['foo', 'bar', 10, 'qux', 'quux', 20]
而字符串中的单个字符却无法被替换。
>>> s = 'foobarbaz'
>>> s[2] = 'x'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
可通过 del 命令删除 list 中的元素。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> del a[3]
>>> a
['foo', 'bar', 'baz', 'quux', 'corge']
5.2 修改 list 中多个元素的值
Python 支持通过切片赋值语法来同时修改 list 中的多个连续元素。
a[m:n] = <iterable>
我们暂时可将此处的 iterable 当做是一个 list。这个赋值操作会将 a 中的 [m:n] 片段整体替换为 iterable。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[1:4]
['bar', 'baz', 'qux']
>>> a[1:4] = [1.1, 2.2, 3.3, 4.4, 5.5]
>>> a
['foo', 1.1, 2.2, 3.3, 4.4, 5.5, 'quux', 'corge']
>>> a[1:6]
[1.1, 2.2, 3.3, 4.4, 5.5]
>>> a[1:6] = ['Bark!']
>>> a
['foo', 'Bark!', 'quux', 'corge']
iterable 中元素的个数不需要和 a[m:n] 片段中元素的个数相等。Python 会根据需要自动伸缩 list。
我们可以用多个元素来替换 list 中的一个元素,只需要将 [m:n] 切片指定为需要替换的单元素片段即可。
a = [1, 2, 3]
>>> a[1:2] = [2.1, 2.2, 2.3]
>>> a
[1, 2.1, 2.2, 2.3, 3]
注意,这和将 list 单个元素替换为另一个 list 对象不同!
a = [1, 2, 3]
>>> a[1] = [2.1, 2.2, 2.3]
>>> a
[1, [2.1, 2.2, 2.3], 3]
我们也可以在 list 上执行纯粹的插入操作:插入元素而不移除其他元素。这可通过将切片索引范围设置为插入位置的索引且长度为0即可:[n:n],n 为插入位置索引。
>>> a = [1, 2, 7, 8]
>>> a[2:2] = [3, 4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6, 7, 8]
有两种方法可用来删除 list 中的多个连续元素。
给要删除的切片赋值为一个空的 list:
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[1:5] = []
>>> a
['foo', 'corge']
通过 del 命令删除 list 切片:
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> del a[1:5]
>>> a
['foo', 'corge']
5.3 向 list 中前插或追加元素
可通过连接(+)或增量赋值(+=)运算符向 list 中前插或追加元素。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a += ['grault', 'garply']
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge', 'grault', 'garply']
>>>
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a = [10, 20] + a
>>> a
[10, 20, 'foo', 'bar', 'baz', 'qux', 'quux', 'corge']
注意,用于和 list 执行连接操作的对象也必须是 list 类型。因此,如果想在 list 中添加一个元素,你需要通过单例 list (只含有一个元素)的方式来包装这个元素。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a += 20
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>>
>>> a += [20]
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge', 20]
补充说明一点。
技术上讲,必须用另一个 list 和源 list 做连接,这个说法并不太正确。更精确的说法是,和源 list执行连接操作的对象必须是一个 iterable。当然,list 本身就是 iterable,因此 list 可被用于和另一个 list 对象进行连接。
字符串也是 iterable。但是,请看一下将字符串连接到 list 对象上时会发生什么。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux']
>>> a += 'corge'
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'c', 'o', 'r', 'g', 'e']
结果可能和你想象的不太一样。
当字符串被迭代遍历时,其结果是一个字符组成的 list。
在上边这个例子中,连接到 list a 的对象也是一个 list:[ 'c', 'o', 'r', 'g', 'e']。
如果你真要往 list 尾部添加一个字符串对象,你需要将这个字符串包装到一个单例 list 中。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux']
>>> a += ['corge']
>>> a
['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
5.4 用于修改 list 的方法
Python 提供了一些内置的方法用于修改 list。
下面介绍这些方法,假如 a 是一个 list 对象。
a.append(<obj>):在 list 尾部追加一个对象。
>>> a = ['a', 'b']
>>> a.append(123)
>>> a
['a', 'b', 123]
请记住:list 方法原地操作目标 list 对象,这些方法不会返回新的 list 对象。
>>> a = ['a', 'b']
>>> x = a.append(123)
>>> print(x)
None
>>> a
['a', 'b', 123]
我们在上边的 list 连接操作时提到,通过连接(+)运算符将 iterable 连接到 list 对象时,iterable 中的元素会被打散,并逐个连接到 list 中。
>>> a = ['a', 'b']
>>> a + [1, 2, 3]
['a', 'b', 1, 2, 3]
>>> [1, 2, 3] + a
[1, 2, 3, 'a', 'b']
a.append() 方法并非如此工作。如果一个 iterable 通过 a.append() 被追加到 list a 中,这个 iterable 会被视为一个单独的对象。
>>> a = ['a', 'b']
>>> a.append([1, 2, 3])
>>> a
['a', 'b', [1, 2, 3]]
因此,可以使用 append() 方法将字符串作为一个单独的实体追加到 list 中。
>>> a = ['a', 'b']
>>> a.append('foo')
>>> a
['a', 'b', 'foo']
a.extend(<iterable>):使用 iterable 中的元素来扩展 list 对象。
这个方法同样用于在 list 尾部追加元素,和 a.append() 不同的是,它将 iterable 中的元素逐个追加到 list 尾部,这和连接(+)运算符相似,确切的说,它和增量(+=)运算符行为是一致的。
>>> a = ['a', 'b']
>>> a.extend([1, 2, 3])
>>> a
['a', 'b', 1, 2, 3]
>>>
>>> a = ['a', 'b']
>>> a += [1, 2, 3]
>>> a
['a', 'b', 1, 2, 3]
a.insert(<index>, <obj>):向 list 中插入一个对象。
a.insert(<index>, <obj>) 将对象 obj 插入到 list a 的 index 指定的位置。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a.insert(3, 3.14159)
>>> a[3]
3.14159
>>> a
['foo', 'bar', 'baz', 3.14159, 'qux', 'quux', 'corge']
a.remove(<obj>):从 list 中移除一个对象。
将对象 obj 从 list a 中删除。若 a 中存在多个值和 obj 相等的对象,每次只删除一个;若 a 中不存在 obj,将触发异常。
>>> a = ['foo', 'bar', 'baz', 'qux', 'bar', 'quux', 'corge']
>>> a.remove('bar')
>>> a
['foo', 'baz', 'qux', 'bar', 'quux', 'corge']
>>> a.remove('babala')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
a.pop(index = -1):从 list 中移除一个元素。
这个方法和 a.remove() 有两点不同:
传入的参数为待删除对象的索引,而不是对象本身
该方法会返回被删除的对象
若未指定参数 index 的值,默认删除 list 的尾元素。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a.pop()
'corge'
>>> a
['foo', 'bar', 'baz', 'qux', 'quux']
>>>
>>> a.pop()
'quux'
>>> a
['foo', 'bar', 'baz', 'qux']
若指定了 index 的值,位于 index 的元素会被删除并被返回。
index 可以是负值。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a.pop(1)
'bar'
>>> a
['foo', 'baz', 'qux', 'quux', 'corge']
>>>
>>> a.pop(-3)
'qux'
>>> a
['foo', 'baz', 'quux', 'corge']
index 默认为 -1,因此,a.pop(-1) 等同于 a.pop()。
6,list 是动态的
从上边几个特性的讲解中,我们已经可以认识到,list 是随着各种操作而动态变化的,它会自行伸缩。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
>>> a[2:2] = [1, 2, 3]
>>> a += [3.14159]
>>> a
['foo', 'bar', 1, 2, 3, 'baz', 'qux', 'quux', 'corge', 3.14159]
>>>
>>> a[2:3] = []
>>> del a[0]
>>> a
['bar', 2, 3, 'baz', 'qux', 'quux', 'corge', 3.14159]
【Python 中的元组(tuple)】
tuple 是 Python 提供的另一个有序对象集合数据类型。
1,定义和使用 tuple
tuple 在各方面和 list 都是相同的,除了下边这两个属性:
Python 使用圆括号(())来定义 tuple 对象
tuple 对象是不可变的
下边给出一个简短的例子来展示 tuple 的定义、索引和切片。
>>> t = ('foo', 'bar', 'baz', 'qux', 'quux', 'corge')
>>> t
('foo', 'bar', 'baz', 'qux', 'quux', 'corge')
>>>
>>> t[0]
'foo'
>>> t[-1]
'corge'
>>> t[1::2]
('bar', 'qux', 'corge')
通过切片来反转字符串和 list 的操作也适用于 tuple。
>>> t[::-1]
('corge', 'quux', 'qux', 'baz', 'bar', 'foo')
如同 list,tuple 对象也是有序的,可包含任意对象,可通过索引访问,可进行切片操作,也可以嵌套定义。
tuple 和 list 最大的不同在于:tuple 对象不能被修改!
>>> t = ('foo', 'bar', 'baz', 'qux', 'quux', 'corge')
>>> t[2] = 'Bark!'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
那么,为什么要使用 tuple 而非 list 呢?
在包含相同的元素的情况下,操作一个 tuple 要比 list 快些,这个速度上的差别可能在元素很多时比较显著。
有时候,处于业务上的需要,我们不希望数据被修改。这时候,tuple 从语法层面为我们提供了保障。
Python 有一个数据类型为字典(dict,后续会介绍到),它的部分组件要求其值是不可变的。tuple 可满足此需求,而 list 不能。
Python 解释器命令行中可以同时输入并显示若干变量,观察输出结果,你会发现,这组变量被隐式解释为一个 tuple 对象了。
>>> a = 'foo'
>>> b = 42
>>> a, 3.14159, b
('foo', 3.14159, 42)
当定义一个 tuple 对象时,有一点需要注意。
如果你定义的是一个空的或者包含两个或更多个元素的 tuple 时,Python 会清楚地明白你的意图,正确创建一个 tuple 对象。
>>> t = ()
>>> type(t)
<class 'tuple'>
>>>
>>> t = (1, 2)
>>> type(t)
<class 'tuple'>
>>> t = (1, 2, 3, 4, 5)
>>> type(t)
<class 'tuple'>
但是,如果定义只包含一个元素的 tuple 对象呢?
>>> t = (2)
>>> type(t)
<class 'int'>
>>>
>>> t = ('hello')
>>> type(t)
<class 'str'>
出现这种结果的原因是,在 Python 中圆括号也被用于定义表达式中各运算符的优先级。(2) 和 ('hello') 均被视为一个表达式,Python 计算其值,分别创建了一个整数对象和一个字符串对象。
如果你真想定义一个只包含一个元素的 tuple,不要忘了在元素之后追加一个逗号(,)。
>>> t = (2,)
>>> type(t)
<class 'tuple'>
>>> t[0]
2
当你在 Python 解释器命令行中输出一个单例 tuple 时,Python 解释器也会显示元素后边的逗号,以提示这是一个 tuple 对象。
>>> print(t)
(2,)
2,tuple 的赋值、打包(pack) 和 解包(unpack)
我们已经知道,一个包含若干元素的 tuple 字面量可以被赋值给一个对象。
>>> t = ('foo', 'bar', 'baz', 'qux')
这个赋值操作好比将 tuple 中的这些元素打包到一个对象中。
>>> t
('foo', 'bar', 'baz', 'qux')
>>> t[0]
'foo'
>>> t[-1]
'qux'
如果这个打包的对象后续被赋值给一个新的 tuple,这些元素会被逐个解包到新 tuple 中的对象中。
>>> (s1, s2, s3, s4) = t
>>> s1
'foo'
>>> s2
'bar'
>>> s3
'baz'
>>> s4
'qux'
使用解包语法时,左侧变量的个数必须和右侧 tuple 中元素的个数匹配。
>>> (s1, s2, s3) = t
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)
>>>
>>> (s1, s2, s3, s4, s5) = t
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 5, got 4)
打包和解包可以在一个语句中组合使用,从而产生一个复合赋值操作。
>>> (s1, s2, s3, s4) = ('foo', 'bar', 'baz', 'qux')
>>> s1
'foo'
>>> s2
'bar'
>>> s3
'baz'
>>> s4
'qux'
在这种情形的赋值和少数其他的使用场景中,Python 允许省略通常用于表示 tuple 的圆括号。
>>> t = 1, 2, 3
>>> t
(1, 2, 3)
>>>
>>> x1, x2, x3 = t
>>> x1
1
>>> x2
2
>>> x3
3
>>>
>>> x1, x2, x3 = 4, 5, 6
>>> x1, x2, x3
(4, 5, 6)
>>>
>>> t = 2,
>>> t
(2,)
有无圆括号都可以正常工作,但为便于理解,尽量还是使用圆括号。
tuple 赋值操作可以产生一些有点奇怪却更地道的 Python 代码。
我们在编程中经常需要交换两个变量的值。在大多数编程语言中,你需要将一个变量存储到一个临时变量中。用代码表示为:
>>> a = 'foo'
>>> b = 'bar'
>>> a,b
('foo', 'bar')
>>>
>>> tmp = a
>>> a = b
>>> b = tmp
>>>
>>> a,b
('bar', 'foo')
在 Python 中,我们可以使用一条语句完成交换操作。
>>> a = 'foo'
>>> b = 'bar'
>>> a, b
('foo', 'bar')
>>>
>>> a,b = b,a
>>>
>>> a,b
('bar', 'foo')
相比使用临时变量,这的确是一个更现代的技术进步。
【结语】
本文详细介绍了 list 和 tuple 的基本属性和使用方法,你将会在 Python 程序中大量使用这两个数据结构。
接下来,我们会学习 Python 中另一个重要的数据类型:字典(dict)。