序列 (字符串、元组、列表) #################################### Python 内置了多种序列,其中最常用的是:列表、元组和字符串(字符串就是由字符组成的序列)。其中只有列表是可以修改的,元组和字符串都是不可以修改的。 在编写程序时,几乎所有情况下都可使用列表来代替元组,一种例外情况是作为字典的键时只能使用元组而不能用列表,因为字典的键是不可变的。 字符串 ************************************ 字符串是由 Unicode 码位构成的不可变序列,是 Python 中最常用的数据类型。字符串用途众多,但主要是表示一段文本,如“Hello World”。 创建字符串 ==================================== 可以用以下方式创建字符串: 1. 单引号: '允许包含有 "双引号" 字符' 2. 双引号: "允许包含有 '单引号' 字符" 3. 三重引号: '''三重单引号''', """三重双引号""" 4. 使用内置函数 str 或 repr 创建字符串很简单,只要为变量分配一个值即可,但是值需要用单引号或双引号将其括起来。定义两种方式是为了更方便的编写程序,当字符串中包含单引号时,就不能用单引号将整个字符串括起来(使用转移符除外),否则解释器将报错。 .. highlight:: none :: >>> greet = 'Hello World' >>> greet = "Hello World" >>> string = "Let's go!" >>> string = 'Let's go!' File "", 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 "", 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) >>> tuple2 = (30,) >>> tuple2 (30,) >>> type(tuple2) # 逗号至关重要 >>> 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 "", line 1, in 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'