序列 (字符串、元组、列表)

Python 内置了多种序列,其中最常用的是:列表、元组和字符串(字符串就是由字符组成的序列)。其中只有列表是可以修改的,元组和字符串都是不可以修改的。

在编写程序时,几乎所有情况下都可使用列表来代替元组,一种例外情况是作为字典的键时只能使用元组而不能用列表,因为字典的键是不可变的。

字符串

字符串是由 Unicode 码位构成的不可变序列,是 Python 中最常用的数据类型。字符串用途众多,但主要是表示一段文本,如“Hello World”。

创建字符串

可以用以下方式创建字符串:

  1. 单引号: ‘允许包含有 “双引号” 字符’

  2. 双引号: “允许包含有 ‘单引号’ 字符”

  3. 三重引号: ‘’’三重单引号’’’, “””三重双引号”””

  4. 使用内置函数 str 或 repr

创建字符串很简单,只要为变量分配一个值即可,但是值需要用单引号或双引号将其括起来。定义两种方式是为了更方便的编写程序,当字符串中包含单引号时,就不能用单引号将整个字符串括起来(使用转移符除外),否则解释器将报错。

>>> greet = 'Hello World'
>>> greet = "Hello World"

>>> string = "Let's go!"
>>> string = 'Let's go!'
File "<stdin>", line 1
string = 'Let's go!'
            ^
SyntaxError: invalid syntax

要创建很长的字符串时(跨越多行的字符串),可使用“三重引号”将其括起来。长字符串可以直接包含单引号、双引号、换行符和转义符。

Note

多行字符串还有一个很好的用法,那就是用作多行注释。

>>> print('''This is a very long string. It continues here.
... And it's not over yet. "Hello, world!"
... Still here.''')
This is a very long string. It continues here.
And it's not over yet. "Hello, world!"
Still here.
>>> print('''This is a very long string.
...     It continues here.''')
This is a very long string.
    It continues here.

还可以使用函数 str 或 repr 将整数、浮点数等值转换成字符串。 str 和 repr 主要的区别,str 能以合理的方式将值转换为用户可读的字符串,如将特殊字符编码转换为相应的字符,将换行符、转义符正确的输出等。而使用 repr 时,通常只会将值转换为合法的 Python 表达式。

>>> str(10.01)
'10.01'
>>> str(100)
'100'
>>> repr(100)
'100'

>>> print(str('Hello \nWorld'))
Hello
World
>>> print(repr('Hello \nWorld'))
'Hello \n world'

转义字符

在字符串中,基本上可以包含任意字符,但是有一些情况需要特殊处理。

上边讲过当用单引号创建字符串时,字符串中将不能在包含单引号,否则程序会报错,Python 会把第一个和第二个引号看错是一对,从而后面的内容就造成了语法错误。需要在字符串中使用特殊字符时,可以用反斜杠 \ 将字符串内的特殊符号进行转义,就是告诉 Python 将字符当作普通字符处理, \ 就叫做转义符。

>>> string = 'Let's go!'
File "<stdin>", line 1
string = 'Let's go!'
            ^
SyntaxError: invalid syntax


>>> string = 'Let\'s go!'
>>> string
"Let's go!"

转义符不仅可以转义特殊字符,还可以转义控制符(如回车键)。当编写程序时,单行的长度太长时可以用转义符转换为多行。需要注意的是,多行转义只用于程序输入时。

这时会有一个问题,当字符串中需要包含怎么办?此时需要用转义符再次去转义(即 \\ )。

>>> string = 'This is a very\
...  long string.'
>>> string
'This is a very long string.'

>>> print('This is a very \nlong string.')
This is a very
long string.
>>> print('This is a very \\n long string.')
This is a very \n long string.

转义符还可以在字符串中包含原本无法包含的字符,例如可以使用 \n 表示换行符。更多的转义字符应用请见下表:

转义字符

描述

\ 在行尾时

续行符

\ \

反斜杠符号

\’

单引号

\”

双引号

\a

响铃

\b

退格(Backspace)

\e

转义

\000

\n

换行

\v

纵向制表符

\t

横向制表符

\r

回车

\f

换页

\oyy

八进制数,yy代表的字符,例如:o12代表换行

\xyy

十六进制数,yy代表的字符,例如:x0a代表换行

原始字符串

在编写程序时,有些情况下会包含大量的 \ 字符,如编写正则表达式时,每次输入 \ 字符都进行转义将使用大量的反斜杠,程序会变得冗长而不易读。

在这样的情况下,原始字符串就会派上大用场,因为它不会对转义符将做特殊处理,而是将字符串中包含的每个字符当作普通字符。原始字符串用前缀 r 表示,后面紧跟字符串。在原始字符串中可以包含任何字符,一个例外是对引号的处理需要像通常那样进行转义,但这时转义符也将包含在最终的字符串中。

# 包含 DOS 路径时
>>> path = 'C:\files'
>>> print(path)
C:files

>>> path = r'C:\files'
>>> print(path)
C:\files

>>> string = r'Let\'s go!'
>>> print(string)
Let\'s go!

另外,原始字符串不能以转义符结尾,除非对其进行转义(但进行转义时,用于转义的反斜杠也将是字符串的一部分)。如果最后一个字符为反斜杠(如 DOS 路径),可以将反斜杠单独作为一个字符串。

>>> print(r'C:\files\bar\\')
C:\files\bar\\

>>> print(r'C:\files\bar' '\\')
C:\files\bar\

请注意,指定原始字符串时可使用单引号或双引号将其括起,也可以使用三重引号将其括起。

字面量格式化

字面量格式化字符串是 python3.6 版本添加的新功能,是一种格式化字符串的语法。 字面量格式化字符串用前缀 f 表示,后面紧跟字符串,字符串中的表达式用大括号 {} 括起来,它会将变量或表达式计算后的值替换进去。

>>> w = 'World'
>>> f'w = {w}'
'w = World'
>>> f'Hello {w}'
'Hello World'

# 使用表达式
>>> f'a = {3+2}'
'a = 5'

# 使用字典
>>> d = {'name': 'Dongxg', 'url': 'www.dongxg.top'}
>>> f"{d['name']}: {d['url']}"
'Dongxg: www.dongxg.top'

元组

元组是一种不可变序列,通常用于储存异构数据的多项集或函数的返回值。

创建元组

可以用以下方式创建元组:

  1. 使用一对圆括号将多个以逗号分隔的值括起来: (a, b, c)

  2. 使用以逗号分隔的多个项: a, b, c

  3. 使用内置函数 tuple

请注意,决定生成元组的是逗号而不是圆括号,但是不建议省略圆括号。

>>> tuple1 = ('Google', 'Runoob', 1997, 2000)
>>> tuple2 = (1, 2, 3, 4, 5)

# 不推荐这种写法
>>> tuple3 = 'a', 'b', 'c', 'd'
>>> tuple3
('a', 'b', 'c', 'd')

需要注意的一点,当元组中只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用:

>>> tuple1 = (50)
>>> tuple1
50
>>> type(tuple1)
<class 'int'>

>>> tuple2 = (30,)
>>> tuple2
(30,)
>>> type(tuple2)
<class 'tuple'>

# 逗号至关重要
>>> 3 * (40 + 2)
126
>>> 3 * (40 + 2,)
(42, 42, 42)

函数 tuple 会将一个序列转换为元组。如果参数已经是元组,就原封不动地返回它。

>>> tuple([1, 2, 3])
(1, 2, 3)

>>> tuple('abc')
('a', 'b', 'c')

>>> tuple((1, 2, 3))
(1, 2, 3)

列表

列表是可变序列,通常用于存放同类项目的集合。因为列表是可变的,可以修改、添加或删除列表内容,所以列表是 Python 中最常用的数据结构。

Note

列表比元组灵活,为什么还要用元组来存储数据?

元组和列表最大的区别就是,列表中的元素可以进行任意修改,列表就好比是用铅笔在纸上写的字,写错了可以擦除重写;而元组就好比是用中性笔在纸上写的字,写了就擦不掉了,写错了就得换一张纸。

这样的差异势必会影响两者的存储方式,我们来直接看下面的例子:

>>> list_demo = []
>>> list_demo.__sizeof__()
40
>>> tuple_demo = ()
>>> tuple_demo.__sizeof__()
24

可以看出,虽然列表和元组都是空的,但元组却比列表少占用 16 个字节,这是为什么呢?

事实上,就是由于列表是动态的,它需要存储指针来指向对应的元素(占用 8 个字节)。另外,由于列表中元素可变,所以需要额外存储分配的长度大小(占用 8 个字节)。

通过对比列表和元组存储方式的差异,我们可以引申出这样的结论,即元组要比列表更加轻量级,所以从总体上来说,元组的性能要优于列表。

元组的不可替代性体现在以下这些场景中:

  1. 元组作为很多内置函数的返回值存在。

  2. 元组比列表的访问和处理速度要快。因此,当元素明确且不涉及修改时,建议使用元组。

  3. 元组可以当做映射中的“键”使用,而列表不行。

创建列表

可以用以下方式创建列表:

  1. 使用一对方括号将多个以逗号分隔的值括起来: [a, b, c]

  2. 使用内置函数 list

  3. 使用列表推导式: [x for x in iterable]

要用方括号把列表值括起来,并用逗号分隔各个列表值,就会新建一个列表。列表值可以是不同类型的值,甚至可以包含其他序列。

list1 = ['Google', 'Runoob', 1997, 2000]
list2 = ['Google', 'Runoob', [1997, 2000]]
list3 = []

函数 list 可以把任何序列转换为列表。

>>> list('Hello')
['H', 'e', 'l', 'l', 'o']

# 以下函数可以将列表转换为字符串
''.join(somelist)

>>> tuple1 = (1,2,3,4,5,6,7,8,9)
>>> list(tuple1)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

修改列表元素

>>> x = [1, 1, 1]
>>> x[1] = 2
>>> x
[1, 2, 1]
>>> x[100] = 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range

不能给不存在的元素赋值,因此如果列表的长度为 2,就不能给索引为 100 的元素赋值。

删除列表元素

可以使用 del 语句来删除列表的的元素。除用于删除列表元素外,del 语句还可用于删除变量。

>>> names = ['Alice', 'Beth', 'Cecil', 'Dee-Dee', 'Earl']
>>> del names[2]
>>> names
['Alice', 'Beth', 'Dee-Dee', 'Earl']

注意:我们会在接下来的章节讨论 remove() 方法的使用

给切片赋值

切片是一项极其强大的功能,而能够给切片赋值让这项功能显得更加强大。你可同时给多个元素赋值,通过使用切片赋值,可将切片替换为长度与其不同的序列。

>>> name = list('Perl')
>>> name
['P', 'e', 'r', 'l']
>>> name[2:] = list('ar')
>>> name
['P', 'e', 'a', 'r']

>>> name[1:] = list('ython')
>>> name
['P', 'y', 't', 'h', 'o', 'n']

# 给一个空切片赋值,相当于插入了一个序列。
>>> name[1:1] = [1, 2, 3]
>>> name
['P', 1, 2, 3, 'y', 't', 'h', 'o', 'n']

# 将一个切片赋值为空列表,来删除切片。
>>> name
['P', 1, 2, 3, 'y', 't', 'h', 'o', 'n']
>>> name[1:6] = []
>>> name
['P', 'h', 'o', 'n']

嵌套列表

列表中可以嵌套列表,访问和修改都与列表的操作相同。

>>> one = ['a', 'b', 'c']
>>> two = [1, 2, 3]
>>> x = [one, two]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c']
>>> x[0][1]
'b'