前言
在Python语言中,所有的数据类型都是类,每一个变量都是类的“实例”。没有基本数据类型的概念,所以整数、浮点数和字符串也都是类。
Python有6种标准数据类型:数字、字符串、列表、元组、集合和字典,而列表、元组、集合和字典可以保存多项数据,它们每一个都是一种数据结构,因此可以称这四种为“数据结构”类型。
本文我们主要介绍数字和字符串类型。
一、数字类型
Python数字类型有4种:整数类型、浮点数类型、复数类型和布尔类型。需要注意的是,布尔类型也是数字类型,它事实上是整数类型的一种。
1.1 整数类型
Python整数类型为 int,整数类型的范围可以很大,可以表示很大的整数,这只受所在计算机硬件的限制。
【提示】Python3 不再区分整数和长整数,所有需要的整数也可以是长整数。
默认情况下一个整数值表示的是十进制数,例如 16 表示的是十进制整数。其他进制,如二进制数、八进制数和十六进制数表示方式如下:
- 二进制:以 0b 或 0B 为前缀,注意 0 是阿拉伯数字,不要误以为是英文字母 o。
- 八进制:以 0o 或 0O 为前缀,第一个字符是阿拉伯数字0,第二个字符是英文字母 o 或 O。
- 十六进制:以 0x 或 0X 为前缀,注意 0 是阿拉伯数字。其中,10~15 分别以 a~f (此处的 a~f 不区分大小写)来表示。
例如,整数值 28 、0b11100、0B11100、0o34、0O34、0x1C 和 0X1C 都表示同一个数字。在 Python shell 中输出结果如下:
>>> 28
28
>>> 0b11100
28
>>> 0O34
28
>>> 0o34
28
>>> 0x1C
28
>>> 0X1c
28
1.2 浮点数类型
浮点数类型主要用来存储小数数值,Python浮点数类型为 float,Python只支持双精度浮点数类型,而且与本机相关。
浮点数类型可以使用小数表示,也可以使用科学计数法,科学计数法中会使用大写或小写的字母 e 表示 10 的指数。如 e2 表示
。
在Python Shell 中运行示例如下:
>>> 1.0
1.0
>>> 0.0
0.0
>>> 3.36e2
336.0
>>> 1.56e-2
0.0156
其中,3.36e2 表示的是 3.36 ×
,1.56e-2 表示的是 1.56 ×
。
【注意】Python不允许除以0,不管是整型数值0还是浮点型数值0,Python都不允许除以0。
1.3 复数类型
复数在数学中是非常重要的概念,无论是在理论物理学,还是在电气工程实践中都经常使用。但是很多计算机编程语言都不支持复数,而Python是支持复数的,这使得Python能够很好地用来进行科学计算。
Python中复数类型为 complex,复数的虚部用字母 j 或 J 来表示。例如,1+2j 表示的是实部为1、虚部为2的复数。在Python Shell 中运行示例如下:
>>> (1+2j) + (1+2j)
(2+4j)
上述代码实现了两个复数的相加运算。
1.4 布尔类型
Python中布尔类型为 bool,bool 是 int 类型的子类,它只有两个值:True 和 False。
【注意】任何类型数据都可以通过 bool() 函数转换为布尔值,那些被认为 “没有的”、“空的” 值会转换为 False,反之转换为 True。如 None(空对象)False、0、0.0、0j(复数)、""(空字符串)、[](空列表)、()(空元组)和 {}(空字典)这些数值会转换为 False,否则是 True。
示例如下:
>>> bool(0)
False
>>> bool(2)
True
>>> bool(1)
True
>>> bool('')
False
>>> bool([])
False
>>> bool({})
False
>>> a = 1 + True
>>> a
2
>>> print(a)
2
上述代码中 bool(2) 和 bool(1) 表达式数据的是 True,这说明数值 2 和 1 都能转换为True,在整数中只有0是转换为 False,其他类型亦是如此。
二、数字类型相互转换
上文中我们学习了四种数字类型,我们不禁会思考一个问题,不同数据类型之间是否可以转换呢?Python通过一些函数可以实现不同数据类型之间的转换,如数字类型之间相互转换以及整数与字符串之间的转换。我们先讨论数字类型的相互转换。
除复数外,其他的三种数字类型(整型、浮点型、布尔型)都可以相互进行转换,转换分为隐式类型转换和显式类型转换。
2.1 隐式类型转换
多个数字类型数据之间可以进行数学计算,由于参与进行计算的数字类型可能不同,此时会发生隐式类型转换。计算过程中隐式类型转换规则如下表1-1 所示。
表1-1 隐式类型转换规则
操作数1类型 | 操作数2类型 | 转换后的类型 |
布尔 | 整数 | 整数 |
布尔、整数 | 浮点 | 浮点 |
布尔类型的值可以隐式转换为整数类型,布尔值 True 转换为整数1,布尔值 False 转换为整数0。在Python Shell 中运行示例如下:
>>> a = 1 + True
>>> print(a)
2
>>> type(a) # ---1
<class 'int'>
>>> a = 1.0 + 1
>>> type(a)
<class 'float'>
>>> print(a)
2.0
>>> a = 1.0 + True
>>> print(a)
2.0
>>> a = 1.0 + 1 + False
>>> print(a)
2.0
>>> type(a)
<class 'float'>
从上述代码表达式的运算结果类型可知表1-1所示的类型转换规则,这里不再赘述。另外,上述代码标记1中使用了 type() 函数,type()函数可以返回传入的变量的数据类型,<class 'int'> 说明是整型,<class 'float'> 说明是浮点型。
2.2 显式类型转换
int()、float() 和 bool()
int() 函数可以将布尔、浮点 和 字符串转换为整数。布尔数值 True 使用 int() 函数返回 1,False 使用 int() 函数返回 0;浮点数值使用 int() 函数会截掉小数部分。int() 函数转换字符串会在下面内容再介绍。
float() 函数可以将布尔、整数和字符串转换为浮点值。布尔数值 True 使用 float()函数返回 1.0,False 使用 float() 函数返回 0.0;整数值使用 float() 函数会加上小数部分“0”。float() 函数转换字符串会在下面内容再介绍。
在Python Shell 中运行示例如下:
>>> int(False)
0
>>> int(True)
1
>>> int(19.6)
19
>>> float(5)
5.0
>>> float(False)
0.0
>>> float(True)
1.0
三、字符串类型
Python中字符串类型是用 str 关键字修饰的。
3.1 字符串表示方式
Python中字符串的表示方式有如下三种:
- 普通字符串:采用单引号“ ' ” 或双引号 “ " ” 包裹起来的字符串。
- 原始字符串(raw string):在普通字符串前加 r,字符串中的特殊字符不需要转义,按照字符串的本来“面目”呈现。
- 长字符串:字符串中包含了换行缩进等排版字符,可以使用三重单引号 “ ''' ” 或三重双引号 “ """ ” 包裹起来,这就是长字符串。
1)普通字符串
很多程序员习惯使用单引号(' ')表示字符串。下面的示例表示的都是 Hello World 字符串。
'Hello World'
"Hello World"
'\u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064' # ---1
"\u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064" # ---2
Python中的字符串采用Unicode编码,所以字符串可以包含中文等亚洲字符。代码第1处和第2处的字符串是用Unicode编码表示的字符串,事实上它表示的也是 Hello World 字符串,可通过 print 函数将 Unicode 编码表示的字符串输出到控制台,则会看到 Hello World 字符串。
>>> s = 'Hello World'
>>> print(s)
Hello World
>>> s = "Hello World"
>>> print(s)
Hello World
>>> s = '\u0048\u0065\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064'
>>> print(s)
Helo World
>>> s = "\u0048\u0065\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064"
>>> print(s)
Helo World
如果想在字符串中包含一些特殊的字符,例如换行符、制表符等,在普通字符串中则需要转移,前面加上反斜杠 “ \ ”,这称为字符转移。表 3-2 所示是常用的几个转义符。
表3-2 转义符
字符表示 | Unicode编码 | 说明 |
\t | \u0009 | 水平制表符 |
\n | \u000a | 换行 |
\r | \u000d | 回车 |
\" | \u0022 | 双引号 |
\' | \u0027 | 单引号 |
\\ | \u005c | 反斜线 |
在 Python Shell 中运行示例如下:
>>> s = 'Hello\n World'
>>> print(s)
Hello
World
>>> s = 'Hello\t World'
>>> print(s)
Hello World
>>> s = 'Hello\' World'
>>> print(s)
Hello' World
>>> s = "Hello' World" ---1
>>> print(s)
Hello' World
>>> s = 'Hello" World' ---2
>>> print(s)
Hello" World
>>> s = 'Hello\\ World' ---3
>>> print(s)
Hello\ World
>>> s = 'Hello\u005c World' ---4
>>> print(s)
Hello\ World
字符串中的单引号(' ') 和双引号(" ") 也可以不用转义。在包含单引号符号的字符串中使用双引号包裹字符串,见代码第1处;在包含双引号字符的字符串中使用单引号包裹字符串,见代码第2处。另外,可以使用Unicode编码替代需要转义的特殊字符,代码第4处和代码第3处是等价的。
2)原始字符串(raw string)
在普通字符串前面加字母 r,表示字符串是原始字符串。原始字符串可以直接按照字符串的字面意思来使用,没有转义字符。在 Python Shell 中运行示例代码如下:
>>> s = 'Hello\tWorld' # ---1
>>> print(s)
Hello World
>>> s = r'Hello\tWorld' # ---2
>>> print(s)
Hello\tWorld
代码第1处是普通字符串,代码第2处是原始字符串,它们的区别只是在字符串前面加字母 r。从输出结果可见,原始字符串中的 \t 没有被当成制表符使用。
3)长字符串
字符串中包含了换行缩进等排版字符时,则可以使用长字符串。在 Python Shell 中运行示例代码如下:
>>> s = '''Hello
... World'''
>>> print(s)
Hello
World
>>> s = """Hello \t
... World"""
>>> print(s)
Hello
World
长字符串中如果包含特殊字符也需要转义。
3.2 字符串格式化
在实际的编程过程中,经常会遇到将其他类型变量与字符串拼接到一起并进行格式化输出的情况。例如计算的金额需要保留小数点后四位,数字需要右对齐等,这些都需要格式化。
在字符串格式化时可以使用字符串的 format() 方法以及占位符。在Python Shell 中运行示例如下:
>>> name = 'Mary'
>>> age = 18
>>> s = '她的年龄是{0}岁。'.format(age) ---1
>>> print(s)
她的年龄是18岁。
>>> s = '{0}芳龄是{1}岁。'.format(name, age) ---2
>>> print(s)
Mary芳龄是18岁。
>>> s = '{1}芳龄是{0}岁。'.format(age, name) ---3
>>> print(s)
Mary芳龄是18岁。
>>> s = '{n}芳龄是{a}岁。'.format(n=name, a=age) ---4
>>> print(s)
Mary芳龄是18岁。
字符串中可以用占位符({} 表示的内容),配合 format() 方法使用,会将 format() 方法中的参数替换占位符内容。占位符可以用参数索引表示,见第1处代码、第2处代码和第3处代码,也可以使用参数名表示占位符,见第4处代码,n 和 a 都是参数名字,需要注意的是,n 和 a 称为形参,name 和 age 称为实参。
表3-3 字符串格式化控制符
控制符 | 说明 |
d、i | 转换为带符号的十进制形式的整数 |
f、F | 转换为十进形式制的浮点数 |
g、G | 十进制整数或浮点数 |
e、E | 科学计算法表示浮点数 |
o | 转换为带符号的八进制形式的整数:符号是小写英文字母 o |
x、X | 转换为带符号的十六进制形式的整数:x 是小写表示,X 是大写表示 |
r | 使用 repr()函数将变量或表达式的值转换为字符串 |
s | 使用 str()函数将变量或表达式的值转换为字符串 |
C | 转化为单字符(只接受整数或单字符字符串) |
格式控制符位于占位符索引或占位符名字的后面,之间用冒号分隔,例如 {1:d} 表示索引为1的占位符格式参数是十进制整数。在Python Shell 中运行示例如下:
>>> name = 'Mary'
>>> age = 18
>>> money = 1234.5678
>>> "{0}芳龄是{1:d}岁".format(name, age) # ---1
'Mary芳龄是18岁'
>>> "{1}芳龄是{0:5d}岁。".format(age, name) # ---2
'Mary芳龄是 18岁。'
>>> "{0}今天收入是{1:f}元。".format(name, money) # ---3
'Mary今天收入是1234.567800元。'
>>> "{0}今天收入是{1:.2f}元。".format(name, money) # ---4
'Mary今天收入是1234.57元。'
>>> "{0}今天收入是{1:10.2f}元。".format(name, money) # ---5
'Mary今天收入是 1234.57元。'
>>> "{0}今天收入是{1:g}元。".format(name, money)
'Mary今天收入是1234.57元。'
>>> "{0}今天收入是{1:G}元。".format(name, money)
'Mary今天收入是1234.57元。'
>>> "{0}今天收入是{1:e}元。".format(name, money)
'Mary今天收入是1.234568e+03元。'
>>> "{0}今天收入是{1:E}元。".format(name, money)
'Mary今天收入是1.234568E+03元。'
>>> '十进制{0:d}的八进制表示为{0:o},十六进制表示为{0:x}'.format(28)
'十进制28的八进制表示为34,十六进制表示为1c'
上述代码第1处中 {1:d} 是格式化十进制整数,代码第2处中 {0:5d} 是指定输出长度为5的字符串,不足用空格补齐。代码第3处中 {1:f} 是格式化十进制浮点数,从输出的结果可见,小数部分太长了。如果想控制小数部分可以使用代码第4处的 {1: .2f} 占位符,其中表示保留小数点后两位。如果想设置长度可以使用代码第5处的 {1: 10.2f} 占位符,其中 10 表示输出总长度,包括小数点和小数部分,不足用空格补位。
补充:字符串格式化方法2:%<控制符>
Python还提供了 “%” 对各种类型的数据进行格式化输出,示例代码如下:
>>> price = 100
>>> print("The book`s price is %s." % price)
The book`s price is 100.
上述代码中的 print 函数包含三个部分,第一部分是格式化字符串(它相当于字符串模板),该格式化字符串中包含了一个 “%s” 占位符,它会被第三部分的变量或表达式的值代替;第二部分固定使用 “%” 作为分隔符。
格式化字符串中的 “%s” 被称为转换说明符(Conversion Specifier),其作用相当于一个占位符,它会被后面的变量或表达式的值代替。“%s” 指定将变量或值使用 str() 函数转换为字符串。
如果格式化字符串中包含多个“%s”占位符,则第三部分也应该对应地提供多个变量,并且使用圆括号将这些变量括起来。示例代码如下:
>>> user = 'Charli'
>>> age = 18
>>> print("%s is a %s years old boy." % (user, age))
Charli is a 18 years old boy.
当使用上面的格式化转换控制符(或转换说明符)时可指定转换后的最小宽度。示例代码如下:
>>> num = -28
>>> print("num is: %6i" % num)
num is: -28
>>> print("num is: %6d" % num)
num is: -28
>>> print("num is: %6o" % num)
num is: -34
>>> print("num is: %6x" % num)
num is: -1c
>>> print("num is: %6X" % num)
num is: -1C
>>> print("num is: %6s" % num)
num is: -28
从上面的输出结果可以看出,此时指定了字符串的最小宽度为6,因此程序转换数值时总宽度为6,程序自动在数值前面补充了三个空格。
在默认情况下,转换出来的字符串总是右对齐,不够宽度时左边用空格补充。Python也允许在最小宽度之前添加一个标志来改变这种默认行为,Python支持如下标志:
- -:指定左对齐
- +:表示数值总要带着符号(正数带“+”,负数带“-”)
- 0:表示不补充空格,而是补充0。
《提示》这三个标志可以多个同时存在。
转换整数(%d)的示例代码如下:
>>> num2 = 30
# 最小宽度为6,右对齐,不够左边补0
>>> print("num2 is: %06d" % num2)
num2 is: 000030
# 最小宽度为6,右对齐,不够左边补0
>>> print("num2 is: %+06d" % num2)
num2 is: +00030
# 最小宽度为6,左对齐
>>> print("num2 is: %-06d" % num2)
num2 is: 30
转换浮点数(%f)的示例代码如下:
>>> my_value = 3.001415926535
# 最小宽度为8,小数点后保留3位,不足左边补空格
>>> print("my_value is: %8.3f" % my_value)
my_value is: 3.001
# 最小宽度为8,小数点后保留3位,不足左边补0
>>> print("my_value is: %08.3f" % my_value)
my_value is: 0003.001
# 最小宽度为8,小数点后保留3位,不足左边补0,始终带符号
>>> print("my_value is: %+08.3f" % my_value)
my_value is: +003.001
如果转换的是字符串格式(%s),Python允许指定转换后的字符串的最大字符数。这个标志被称为精度值,该精度值被放在最小宽度之后,中间用点号 (.) 隔开。示例代码如下:
>>> the_name = "Charlie"
# 只保留3个字符,最小宽度为10,右对齐,宽度不足左边补空格
>>> print("the name is: %10.3s" % the_name)
the name is: Cha
# 只保留3个字符,没有设置最小宽度,则按实际宽度输出
>>> print("the name is: %.3s" % the_name)
the name is: Cha
3.3 字符串查找
在给定的字符串中查找子字符串是比较常见的操作。字符串类(str) 中提供了 find 和 rfind 方法用于查找子字符串,返回值是查找到的子字符串所在的位置,没有找到返回 -1。下面只具体说明 find 和 rfind 方法。
str.find(sub[, start[, end]])
在索引 start 和 end 之间查找子字符串 sub,如果找到返回最左端位置的索引,如果没有找到返回-1。start 是开始索引,end 是结束索引,这两个参数都可以省略,如果 start 省略说明查找从字符串头开始;如果 end 省略说明查找到字符串结尾;如果全部省略就是查找整个字符串本身。
str.rfind(sub[, start[, end]])
与 find 方法类似,区别是如果找到返回最右端位置的索引。如果在查找的范围内只找到一处字符串,那么这里 find 和 rfind 方法返回值是相同的。
【提示】在Python 文档中,[ ] 表示可以省略部分,find 和 rfind 方法参数 [, start[, end]] 表示 start 和 end 都可以省略。
在Python Shell 中运行示例代码如下:
>>> source_str = "There is a string accessing example."
>>> len(source_str) ---1
36
>>> source_str[16] ---2
'g'
>>> source_str.find('r')
3
>>> source_str.rfind('r')
13
>>> source_str.find('ing')
14
>>> source_str.rfind('ing')
24
>>> source_str.find('e', 15)
21
>>> source_str.rfind('e', 15)
34
>>> source_str.find('ing', 5)
14
>>> source_str.rfind('ing', 5)
24
>>> source_str.find('ing', 18, 28)
24
>>> source_str.rfind('ing', 18, 28)
24
>>> source_str.rfind('ingg', 5)
-1
上述代码第1处 len(source_str) 返回字符串长度,注意 len 是函数,不是字符串类的一个方法,它的参数是字符串。代码第2处 source_str[16] 表示访问字符串中索引为16的字符。
source_str.find('ing', 5) 和 source_str.rfind('ing', 5)
图3-1 source_str 字符串索引
【提示】函数和方法的区别是,方法是定义在类中的函数,在类的外部调用时需要通过类或对象调用,例如上述代码 source_str.find('r') 就是调用字符串类对象 source_str 的 find 方法,find 方法是在 str 类中定义的。而通常的函数不是类中定义的,也称为顶层函数,它们不属于任何一个类,调用时直接使用函数即可,例如上述代码中的 len(source_str),就调用了 len 函数,只不过它的参数是字符串对象 source_str。
3.4 字符串与数字相互转换
在实际的编程过程中,经常会用到字符串与数字相互转换。下面从不同的方面介绍字符串与数字相互转换。
1)字符串转换为数字
字符串转换为数字可以使用 int() 和 float() 函数实现。上文 2.2 节介绍了这两个函数实现数字类型之间的转换,事实上这两个函数也可以接收字符串参数,如果字符串能成功转换为数字,则返回数字,否则引发异常。
在Python Shell 中运行示例代码如下:
>>> int('9')
9
>>> int('9.6')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '9.6'
>>> float('9.6')
9.6
>>> int('AB')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'AB'
默认情况下,int() 函数都将字符串参数当成十进制数字进行转换,所以 int('AB') 会失败。int() 函数也可以指定基数(即进制),在Python Shell 中运行示例如下:
>>> int('AB', 16)
171
2)数字转换为字符串
数字转换为字符串有很多方法,3.2 节中介绍的字符串格式化方法可以将数字转换为字符串。另外,Python 中字符串提供了 str() 函数。
可以使用 str()
>>> str(3.24)
'3.24'
>>> str(True)
'True'
>>> str([])
'[]'
>>> str([1, 2, 3])
'[1, 2, 3]'
>>> str(34)
'34'
从上述代码可知,str() 函数很强大,什么类型都可以转换为字符串。但缺点是不能格式化,如果需要格式化字符串可以使用 format 方法。
在Python Shell 中运行示例代码如下:
>>> '{0:.2f}'.format(3.25)
'3.25'
>>> '{0:.1f}'.format(3.25)
'3.2'
>>> '{0:10.1f}'.format(3.25)
' 3.2'
>>> '{:10.1f}'.format(3.25)
' 3.2'
【提示】在使用 format 方法格式化字符串时,如果只有一个参数,占位符索引可以省略掉。
补充:使用 repr() 函数将数字转换为字符串
使用 repr() 函数将数字类型转换为字符串类型。示例代码如下:
>>> a = 10
>>> repr(a)
'10'
>>> repr(3.24)
'3.24'
>>> repr(True)
'True'
>>> repr(False)
'False'
str() 和 repr() 函数都可以将数字转换成字符串,其中 str 本身是Python内置的类型(和 int、float 一样),而 repr() 则只是一个函数。此外,repr 还有一个功能,它会以Python表达式的形式来表示值。对比如下代码的运行结果:
>>> st = "I will play my life"
>>> print(st)
I will play my life
>>> print(repr(st))
'I will play my life'
上面代码中,st 本身就是一个字符串,但程序依然使用了 repr() 函数对字符串进行转换,可以看到两个print语句的输出结果有所不同。
如果直接使用print()函数输出字符串,将只能看到字符串的内容,没有引号;但如果先使用 repr() 函数对字符串进行处理,然后再使用print()执行输出,将可以看到带引号的字符串——这就是字符串的Python的表达式形式。
《提示》在Python Shell 交互式解释器中输入一个变量或表达式时,Python会自动使用 repr() 函数处理该变量或表达式。
3.5 使用 input() 函数获取用户输入
input() 函数用于向用户生成一条提示,然后获取用户输入的内容。由于 input() 函数总会将用户输入的内容放入字符串中,因此用户可以输入任何内容,input() 函数总是返回一个字符串。
例如如下程序:程序清单:input_test.py
# coding=utf-8
msg = input("请输入你的值:")
print(type(msg))
print(msg)
示例运行结果:
F:\python_work\Python基础\字符串>python input_test.py
请输入你的值:2
<class 'str'>
2
F:\python_work\Python基础\字符串>python input_test.py
请输入你的值:1.2
<class 'str'>
1.2
F:\python_work\Python基础\字符串>python input_test.py
请输入你的值:Hello
<class 'str'>
Hello
从上面的运行过程可以看出,无论输入哪种内容,始终可以看到 input() 函数返回字符串类型(str),程序总会将用户输入的内容转换成字符串。
3.6 字节类型 — bytes
字节串。
bytes 和 str 除操作的数据单元不同之外,它们支持的所有方法都基本相同,bytes 也是不可变序列。
bytes 对象只负责以字节(二进制格式)序列来记录数据,至于这些数据到底表示什么内容,完全由程序决定。如果采用合适的字符集,字符串可以转换成字节串;反过来,字节串也可以恢复成对应的字符串。
由于 bytes 保存的就是原始的字节(二进制格式)数据,因此 bytes 对象可用于在网络上传输数据,也可用于存储各种二进制格式的文件,比如图片、音乐等文件。
如果希望将一个字符串转换成 bytes 对象,有如下三种方式。
- 如果字符串内容都是 ASCII 字符,则可以通过字节在字符串之前添加字母 b 来构建字节串值。
- 调用 bytes() 函数(本质是 bytes 类的构造方法)将字符串按指定字符集转换成字节串,如果不指定字符集,默认使用 UTF-8 字符集。
- 调用字符串本身的 encode() 方法将字符串按指定字符集转换成字节串,如果不指定字符集,默认使用 UTF-8 字符集。
例如,如下程序示范了如何创建字节串。程序清单:bytes_test.py
# coding=utf-8
# 创建一个空的bytes对象
b1 = bytes()
# 创建一个空的bytes值
b2 = b''
# 通过前缀b指定hello是bytes类型的值
b3 = b'hello'
print(b3)
print(b3[0])
print(b3[2:4])
# 调用bytes()方法将字符串转换成bytes对象
b4 = bytes('I love Python Programming', encoding='utf-8')
print(b4)
# 利用字符串的encode()方法编码成bytes,默认使用UTF-8字符集
b5 = "学习 Python 很有趣".encode('utf-8')
print(b5)
运行结果:
F:\python_work\Python基础\字符串>python bytes_test.py
b'hello'
104
b'll'
b'I love Python Programming'
b'\xe5\xad\xa6\xe4\xb9\xa0 Python \xe5\xbe\x88\xe6\x9c\x89\xe8\xb6\xa3'
上面程序中,b1~b5都是字节串对象,该程序示范了以不同方式来构建字节串对象。其中,b2、b3 都是直接在 ASCII 字符串前添加 b 前缀来得到字节串的;b4 调用 bytes() 函数来构造字节串;而 b5 则调用字符串的 encode() 方法来构建字节串。
在字节串中每一个数据单元都是字节,也就是8位二进制,其中每4位(相当于4位二进制数,最小值为9,最大值为15)可以用一个十六进制数来表示,因此每字节需要两个十六进制数表示,所以可以看到上面运行的程序的输出是:b'\xe5\xad\xa6\xe4\xb9\xa0 Python \xe5\xbe\x88\xe6\x9c\x89\xe8\xb6\xa3' ,比如 \xe5 就表示 1 字节,其中 \x 表示十六进制,e5 就是两位的十六进制数。
如果程序获得了 bytes 对象,也可调用 bytes 类对象的 decode() 方法将其解码成字符串,例如,在上面的程序中添加如下代码。
# 将 bytes 对象解码成字符串,默认使用UTF-8字符集进行解码
st = b5.decode('utf-8')
print(st)
运行结果为:
学习 Python 很有趣
【知识拓展】字符集的概念
计算机底层并不能保存字符,但程序总是需要保存各种字符的,那该怎么办呢?计算机科学家就想了一个办法:为每个字符编号,当程序要保存字符时,实际上保存的是该字符对应的编号;当程序读取字符时,读取的其实也是编号,接下来要去查 “编号-字符对应表”(简称码表)才能得到实际的字符。因此,所谓的字符集,就是所有字符的编号组成的综合。早期美国人给英文字符、数字、英文标点符号等字符进行了编号,他们认为所有字符加起来顶多 100 多个,只要 1 字节(8位,支持 256 个字符编号)即可为所有字符编号——这就是 ASCII 字符集。后来,亚洲国家纷纷为本国文字进行编号——即制订本国的字符集,但这些字符集并不兼容。于是美国人又为世界上所有书面语言的字符进行了统一编号,这次他们用了两个字节(16位,支持65536个字符编号),这就是 Unicode 字符集。实际使用的 UTF-8、UTF-16 等其实都属于 Unicode 字符集。
由于不同人对字符的编号完全可以很随意,比如同一个 “爱” 字,我可以为其编号为 99,别人可以为其编号为 199,所以同一个编号在不同的字符集中代表的字符完全有可能是不同的。因此,对于同一个字符,如果采用不同的字符集来生成 bytes 对象,就会得到不同的 bytes 对象。
《补充说明》字符串还有其他的内容,如拼接字符串、字符串大小写转换、删除字符串空白字符、字符串替换、字符串分割、连接等。
参考
《Python从小白到大牛(第1版-2018).pdf》第6章 - 数据类型
《疯狂Python讲义(2018.12).pdf》第2章 - 变量和简单类型
《Python编程:从入门到实践(2016.7).pdf》第2章 - 变量和简单数据类型