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 == bFalse>>> a is bFalse>>>>>> [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 中的元素
list 中的单个元素可使用方括号通过元素索引来访问,这和访问字符串中的单个字符的方法非常相似。list 元素索引也是以 0 为基础的。
考虑下边这个 list:
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']
这个 list 中元素的索引如下所示:
下边是访问 list 元素的 Python 代码:
>>> a[0]'foo'>>> a[2]'baz'>>> a[5]'corge'
实际上,所有字符串索引相关操作基本上都适用于 list。比如,list 负值索引是从 list 尾部进行计数的。
>>> a[-1]'corge'>>> a[-2]'quux'>>> a[-5]'bar'
切片操作同样适用于 list。
假如 a 是一个 list 对象,表达式 a[m:n] 返回一个 a 的子 list,起始于索引 m,终止于索引 n,但不包含索引为 n 的元素。
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']>>> a[2:5]['baz', 'qux', 'quux']
其他适用于字符串的切片特性也适用于 list 切片操作。
  • 可使用正值或负值索引

    >>> 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:] == aTrue
  • 可指定切片的步长,步长可为正值或负值

    >>> 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 sTrue
若 a 是一个 list,a[:] 返回的是对 list a 的一份拷贝:
>>> a = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge']>>> a[:]['foo', 'bar', 'baz', 'qux', 'quux', 'corge']>>> a[:] is aFalse
Python 的一些运算符和内置函数可用于操作 list,使用方法和操作字符串类似。
  • in 和 not in 运算符

    >>> a['foo', 'bar', 'baz', 'qux', 'quux', 'corge']>>> 'qux' in aTrue>>> 'thud' not in aTrue
  • 连接(+)和复制(*)运算符

    >>> 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'
看起来,list 和字符串行为很相似。这并不是偶然的。它们都是一个更一般的对象类型 iterable 的特例。我们会在后续的学习中了解如何定义一个 iterable。
在我们上边的例子中,list 对象在使用之前总是先被赋值给一个变量,我们也可以直接在 list 常量上执行各种操作。
>>> ['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 xFalse>>> '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 += 20Traceback (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) = tTraceback (most recent call last): File "<stdin>", line 1, in <module>ValueError: too many values to unpack (expected 3)>>>>>> (s1, s2, s3, s4, s5) = tTraceback (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>>> x11>>> x22>>> x33>>>>>> 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)。


(0)

相关推荐