序列 (字符串、元组、列表)¶
Python 内置了多种序列,其中最常用的是:列表、元组和字符串(字符串就是由字符组成的序列)。其中只有列表是可以修改的,元组和字符串都是不可以修改的。
在编写程序时,几乎所有情况下都可使用列表来代替元组,一种例外情况是作为字典的键时只能使用元组而不能用列表,因为字典的键是不可变的。
字符串¶
字符串是由 Unicode 码位构成的不可变序列,是 Python 中最常用的数据类型。字符串用途众多,但主要是表示一段文本,如“Hello World”。
创建字符串¶
可以用以下方式创建字符串:
单引号: ‘允许包含有 “双引号” 字符’
双引号: “允许包含有 ‘单引号’ 字符”
三重引号: ‘’’三重单引号’’’, “””三重双引号”””
使用内置函数 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'
元组¶
元组是一种不可变序列,通常用于储存异构数据的多项集或函数的返回值。
创建元组¶
可以用以下方式创建元组:
使用一对圆括号将多个以逗号分隔的值括起来: (a, b, c)
使用以逗号分隔的多个项: a, b, c
使用内置函数 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 个字节)。
通过对比列表和元组存储方式的差异,我们可以引申出这样的结论,即元组要比列表更加轻量级,所以从总体上来说,元组的性能要优于列表。
元组的不可替代性体现在以下这些场景中:
元组作为很多内置函数的返回值存在。
元组比列表的访问和处理速度要快。因此,当元素明确且不涉及修改时,建议使用元组。
元组可以当做映射中的“键”使用,而列表不行。
创建列表¶
可以用以下方式创建列表:
使用一对方括号将多个以逗号分隔的值括起来: [a, b, c]
使用内置函数 list
使用列表推导式: [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'