Python 中的数据类型

从这一小节开始,我们将正式学习 Python 基本语法规则。本文首先来认识 Python 中的基本数据类型

看过电影《奇异博士》的同学肯定记得:奇异博士利用魔法制造了镜像世界进行战斗,减少对现实世界的破坏。

就像 Python 世界就可以看作现实世界的【镜像】,我们想要做到的就是在镜像世界里面高效地解决现实世界里的繁琐任务。这首先就要求 Python 【镜像世界】中必然存在与现实世界物体(研究对象)对应的抽象表达,比如现实世界中最常见的数字、文字、图像、声音等等,在 Python 世界统一被称为:【数据】,有了数据才有后续的一切。


数据呀,『长相』不一样(有不同的类型),各司其职。只有认清各类型数据的『长相』,了解它们的功能,才能在镜像世界里完成现实世界的任务。所以,你应该认识到数据类型相关的小节都是重点,数据都玩不好还想啥(pi)吃?敲黑板…。

基础数据类型

Python3 中支持六种标准的基础数据类型:

  • Number(数值)
  • String(字符串)
  • Tuple(元组)
  • List(列表)
  • Dictionary(字典)
  • Set(集合)

Python3 的六个标准数据类型中:

  • 不可变数据(3 个):Number(数值)、String(字符串)、Tuple(元组);
  • 可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。

关于数据类型的可变和不可变属性可参考:Python-中的可变和不可变对象,等学过 Tuple(元组)、List(列表)或字典(Dict)、集合(Set)之后,可以返回来看这一部分内容,可以帮助我们进一步掌握上述六种标准数据类型的用法。


在开始学习数据类型之前,我们先来看 Python 中的变量概念:

Python 变量和常量

–> 变量是什么?

变量你可以将其看成是一个个带有标签(名字)的小盒子,用来存放我们的数据。

严格来说,

在 Python 中,变量就是指向一个计算机内存单元的引用,它没有类型。我们所说的 “变量的类型” 是变量指向的内存中数据对象的类型。

–> 常量又是什么?

和变量相对应的是 常量(Constant),它们都是用来“盛装”数据的小箱子,不同的是:变量保存的数据可以被多次修改,而常量一旦保存某个数据之后就不能修改了(事实上,Python 并没有严格的对常量进行控制,只是约定俗成的规定常量名必须全部大写)。


变量定义

Python 中变量的定义不需要声明,赋值后可直接使用(即赋值时创建),这很便捷。


变量赋值

数学等号(=)用来给变量赋值。

赋值运算符(=)左边是一个变量名,右边是存储在变量中的值。例如:

1
2
3
counter = 100          # 整型变量
miles = 1000.0 # 浮点型变量
name = "python" # 字符串型变量

多变量赋值(不推荐) >>>>

Python 允许你同时为多个变量赋值(注意:语法规范不允许这么使用),例如:

1
a = b = c = 1

或者:

1
a, b, c = 1, 2, "python"    # 用法唯一,没有 a, b, c = 1;a, b, c = 1, 2

变量的内存表示

当我们定义:

1
test1 = 'ABC'

时,Python 解释器干了两件事情:

  1. 在内存中创建了一个'ABC'的字符串;
  2. 在内存中创建了一个名为 test 的变量,并把它指向'ABC'

当然,也可以把一个变量 test1 赋值给另一个变量 test2,这个操作实际上是把变量 test2 指向变量 test1 所指向的数据,例如下面的代码:

1
2
3
4
5
test1 = 'ABC'
test2 = test1
test1 = 'XYZ'

print(test2) # 输出:ABC

=============================== Python 缓存重用机制 ================================

事实上,Python 初始化变量时,不一定开辟新的内存空间!怎么理解?!!

这是因为 Python 中存在缓存重用机制,也称为常量池(Constants Pool)机制,来判断是否需要新开辟内存。由于篇幅原因,关于缓存重用机制请参见博文:Python 中的缓存重用机制(常量池)


动态语言特性

Python 中可以把任意数据类型赋值给变量。同一个变量可以反复赋值,而且可以是不同类型的值,例如:

1
2
3
test = 100          # 整型变量
test = 1000.0 # 浮点型变量
test = "python" # 字符串

这种变量本身类型不固定的语言称之为 动态语言,也称为 弱类型语言

与之相对的是 静态语言(强类型语言),静态语言在定义变量时必须指定变量类型,如果赋值的数据类型和定义类型不匹配时,就会报错(例如:强类型语言的代表:Java,C,C++ 等)。


Python 数据类型

下面我们将开始分别说明上述提到的六种标准数据类型:Number(数值)、String(字符串)、Tuple(元组)、List(列表)、Set(集合)、Dictionary(字典)。

Number(数值)

Number 数据类型用于存储数值,Python 中支持四种不同的数值类型:整数(int)、布尔型(bool)、浮点数(float)和复数(complex)。

数值类型

[1] –> 整型(int)

Python3 中只有一种整数类型 int,表示为长整型。Python3 整型是没有限制大小的,可以当作 Long 类型使用,所以 Python3 没有 Python2 的 Long 类型。

也就是说 int 可以处理任意大小(无限)的整数,当然包括负整数,在程序中的表示方法和 数学上的写法 一模一样,例如:1100-80800,等等(十进制写法,Decimal)。

计算机由于使用二进制,所以有时候用 二进制(Binary)、八进制(Octal)或者十六进制(Hexadecimal) 表示整数比较方便:

1
2
3
4
5
6
7
8
9
10
11
>>> number = 0xA0F # 十六进制(A~F, A -> 10)
>>> number
2575

>>> number= 0o37 # 八进制
>>> number
31

>>> number = 0b1111111 # 二进制
>>> number
127

–> 如何将十进制转化为其它进制数?

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> num = 127

# 将一个整数(d/0o/0x)转化为二进制数:
>>> bin(num)
'0b1111111'

# 将一个整数(d/0b/0x)转化为八进制数:
>>> oct(num)
'0o177'

# 将一个整数(d/0o/0b)转化为十六进制数:
>>> hex(num)
'0x7f'

[2] –> 浮点型(float)

Python 只有一种小数类型,就是 float

浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,比如:1.23 ×10^912.3 × 10^8 是完全相等的。

浮点数可以用 数学写法,如 1.233.14-9.01 等等。但是对于很大或很小的浮点数,就必须用 科学计数法 表示,把 10e 替代,1.23 × 10^9 就是1.23e9,或者 12.3e8,0.000012 可以写成1.2e-5,等等。

1
2
3
4
>>> num = 1.23e5
123000.0
>>> num = 1.23e-3
0.00123

| >>> ================================ 浮点数计算精度问题 ================================ <<< |

注意:永远不要直接比较两个浮点的大小。

1
2
# 尝试一下比较如下大小:
0.1 + 0.2 > 0.3 // true

这是由于计算机中浮点型数值的计算是不精确的(十进制和二进制转换引发),这种问题不仅在 Python 中存在,在所有支持浮点数运算的编程语言中都会遇到,它不光是 Python 的 Bug。

详情请关注编程基础系列博文:

[ >>>> 编程基础之进制详解 <<<< ]
[ >>>> 为什么 0.1 + 0.2 不等于 0.3? <<<< ]

明白了问题产生的原因之后,那么该如何解决呢?

Python 的浮点数运算而言,大多数计算机每次计算误差不会超过 2^53,但这对于大多数任务来说已经足够了。

如果对于会计方面的应用和有高精度要求的应用场景,可以借助 decimal 或者 fractions 分数模块,能够很好地解决浮点类型数之间运算的问题。关于高精度浮点数运算应用场景解决方案可参见 —> [ >>>> Python 浮点数精确运算解决方案 <<<< ]。


[3] –> 布尔型(bool)

Python3 中,布尔值有 TrueFalse 两种,并把 TrueFalse 定义成关键字了(请注意大小写)。并且 bool 类型继承自整型 int, 故 可以直接和数字运算,它们的值对应 True == 1False == 0

1
2
3
4
5
6
>>> print(True==1)
True
>>> print(False==0)
True
>>> print(True + 1)
2

–> 也可以通过比较运算符(><==!=)计算出来:

1
2
3
4
5
6
7
8
>>> True
True
>>> False
False
>>> 3 > 2
True
>>> 3 > 5
False

–> 布尔值还可以进行 andornot 逻辑运算:

  • and 运算是”与运算”,只有所有都为 Trueand 运算结果才是True
  • or 运算是”或运算”,只要其中有一个为 Trueor 运算结果就是 True
  • not 运算是”非运算”,它是一个单目运算符,把 True 变成 FalseFalse 变成 True
1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> print(True and "test")
test
>>> print(False and "test")
False
>>> print(False or "test")
test
>>> print(True or "test")
True
>>> print(not "test")
False
>>> print(not 0)
True
>>> print(not 1)
False

–> 布尔值还常常用于 条件判断(或 while 循环)中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Python 中,所有的对象都可以进行真假值的测试,包括字符串、元组、列表、字典、集合、对象
>>> print(bool([]))
False
>>> print(bool([1,2,3]))
True
>>> print(bool(None))
False
>>> print(bool(0))
False
>>> print(bool(""))
False
>>> print(bool({}))
False

# 条件判断中以下数值会被认为是 False:
# 为零的数:0 or 0.0;
# 空字符串:'',"";
# 空值:None;
# 空集合:(),[],{};
# 其他的值都认为是 True。
>>> if ():
... print(True)
... else:
... print(False)
...
False
>>> if "123":
... print(True)
... else:
... print(False)
...
True

# 注意(仅在条件判断中):
>>> print(True and [])
[]
>>> "" and False
''

[4] –> 复数(complex )

Python还支持复数,复数由实数部分和虚数部分构成,可以用 a + bj ,或者 complex(a,b) 表示。注意,复数的实部 a 和虚部 b 都是浮点型数。 例如:

1
2
3
4
5
a = 1 + 2j
b = 1.1 + 2.2j
>>> a = complex(1,2)
>>> print(a)
(1+2j)

Number 相关运算

[1] – > type(object) && isinstance(objecrt, class_or_tuple)

内置的 type() 函数可以用来查询变量所指的 对象类型

1
2
3
>>> a,b,c,d = 12, 2.3, True, 1+2j
>>> print(type(a), type(b), type(c), type(d))
<class 'int'> <class 'float'> <class 'bool'> <class 'complex'>

此外还可以用 isinstance() 来判断:

1
2
3
4
5
6
>>> isinstance(a, int)
True

# 可以看出 bool 型也是 int 型的一种:
>>> isinstance(c, int)
True

那么,isinstance()type() 的区别在于?:

  • type() 不会认为子类是一种父类类型。
  • isinstance() 会认为子类是一种父类类型。
1
2
3
4
5
6
7
8
9
10
>>> type(c) == bool
True
>>> type(c) == int
False
>>> isinstance(c, int)
True

# 注意:
>>> isinstance(True, (int,float))
True

[2] –> del

我们知道当变量被赋值时,Number 对象将会被创建:

1
2
3
>>> number1 = 10
>>> number2 = 1.2
>>> number3 = True

我们还可以使用 del 语句删除 单个或多个对象的引用(变量),例如:

1
2
3
4
5
6
>>> del number1
>>> del number2, number3
>>> print(number1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'number2' is not defined

[3] –> Number 数据类型之间的转换

有时候,我们需要对数据内置的类型进行转换。对于数据类型的转换,你只需要将数据类型作为函数名即可。

  • int(x) 将 x 转换为一个整数。
  • float(x) 将 x 转换到一个浮点数。
  • complex(x) 将 x 转换到一个复数,实数部分为 x,虚数部分为 0。
  • complex(x, y) 将 x 和 y 转换到一个复数,实数部分为 x,虚数部分为 y。x 和 y 是数字表达式。

注意:int、float 和 bool 可以相互转换;int、float 和 bool 均可以转换为 complex,但不可以反转。

1
2
>>> float(1+2j)
TypeError: can't convert complex to float

[4] –> 数值计算

Python 解释器可以作为一个简单的计算器,您可以在解释器里输入一个数学表达式,它将输出表达式的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>>5 + 4  # 加法
9
>>> 4.3 - 2 # 减法
2.3
>>> 3 * 7 # 乘法
21
>>> 2 / 4 # 除法,得到一个浮点数
0.5
>>> 2 // 4 # 向下取整
0
>>> 17 % 3 # 取余
2
>>> 3 % 17
3
>>> 2 ** 5 # 幂运算
32

注意:int,bool 以及 float 进行混合计算时,会得到浮点数:

1
2
3
4
5
6
>>> 15 // 3.0
5.0
>>> 12 / True
12.0
>>> 13 - 2.0
11.0

[5] –> 常用数学函数

使用数学函数前,我们需要导入相应的 math 模块:

1
import math

下面来看常用数学函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 常用数学常量
>>> math.pi
3.141592653589793
>>> math.e
2.718281828459045

# 返回数字的绝对值
>>> a = -10
>>> abs(a)
10
>>> math.fabs(a)
10.0

# 返回数字的向上取整(ceil,天花板)结果
>>> b = 12.3
>>> math.ceil(b)
13
>>> c = 12.8
>>> math.ceil(c)
13

# # 返回数字的向下取整(floor,地板)结果
>>> math.floor(c)
12
>>> math.floor(b)
12

# 返回 e 的 x 次幂
>>> math.exp(1)
2.718281828459045

# log 函数
>>> math.log(100)
4.605170185988092
>>> math.log(100, 10)
2.0
# 返回以 10 为基数的 x 的对数
>>> math.log10(100)
2.0

# 返回给定参数的最大值,参数可以为序列。
>>> max(1, 2.0, 3, 4)
4
# 返回给定参数的最小值,参数可以为序列。
>>> min(1, 2.0, 3, 4)
1

# pow(x,y):返回 x**y 运算后的值
>>> pow(2,4)
16

# round(x,n):返回浮点数 x 的四舍五入值,如给出 n 值,则代表舍入到小数点后的位数
>>> round(2.71828,3)
2.718

# sqrt(x):返回数字 x 的平方根
>>> math.sqrt(100)
10.0

三角函数相关方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import math

# math.sin(x):返回 x 弧度的正弦值
# math.cos(x):返回 x 弧度的余弦值
# math.tan(x):返回 x 弧度的正切值

# math.asin(x):返回 x 的反正弦弧度值
# math.acos(x):返回 x 的反余弦弧度值
# math.atan(x):返回 x 的反正切弧度值

# math.degrees(x):将弧度转换为角度
>>> math.degrees(math.pi/2)
90.0
# math.radians(x):将角度转换为弧度
>>> math.radians(90)
1.5707963267948966
>>> math.pi/2
1.5707963267948966

String(字符串)

字符串是 Python 中最常用的数据类型,是以单引号 ' 或双引号 " 括起来的任意文本,同时使用反斜杠 \ 来转义特殊字符。

创建字符串很简单,只要为变量分配一个值即可。例如:

1
2
3
4
>>> str1 = 'abc'
>>> str2 = 'XYZ'
>>> type(str1)
<class 'str'>

这里,''"" 本身只是一种表示方式,不是字符串的一部分,因此,字符串'abc'只有abc这3个字符。

注意,Python 不支持单独的字符类型(char 型),一个字符就是长度为 1 的字符串。

–> del 删除字符串变量 >>>>

可以使用 del 语句删除 单个或多个对象的引用(变量),例如:

1
2
3
4
5
6
7
>>> del str1
>>>> del str2 str3
>>> print(str1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'str1' is not defined


单引号 ' 或双引号 " 使用

如果 ' 本身也是字符串中的一个字符,那就可以用 "" 括起来,比如 "I' am OK"

当然如果 " 也是字符串本身的一个字符的话,外面可以用 '' 括起来,如:'I"m OK'。同理,如果 ' 是字符串本身的一个字符的话,外面可以用 "" 括起来,如:"I'm OK"。注意,都一致的话会报错:

1
2
3
4
5
>>> print('I'm ok')
File "<stdin>", line 1
print('I'm ok')
^
SyntaxError: invalid syntax

但切记不要混合使用,如下:

1
2
# 语法错误:
print("I'm OK')

思考一下?–> 如果字符串内部既包含 ' 又包含 " 怎么办???

此时只能使用转义字符 \ 来标识,比如:

1
'I\'m \"OK\"!'

表示的字符串内容是:

1
I'm "OK"!

字符串中的转义字符

转义字符 \ 可以转义很多字符。比如,\n 表示换行;\t 表示制表符;\r 表示回车;字符 \ 本身也要转义,所以\\表示的字符就是\

可以在 Python 的交互式命令行用 print() 打印字符串看看:

1
2
3
4
5
6
7
8
>>> print('I\'m ok.')
I'm ok.
>>> print('I\'m learning\nPython.')
I'm learning
Python.
>>> print('\\\n\\')
\
\

字符串换行

Python 不是格式自由的语言,它对程序的换行、缩进都有严格的语法要求。要想换行书写一个比较长的字符串,必须在行尾添加反斜杠 \,请看下面的例子:

1
2
3
s2 = 'It took me six months to write this Python tutorial. \
Please give me more support. \
I will keep it updated.'

上面 s2 字符串的比较长,所以使用了转义字符 \ 对字符串内容进行了换行,这样就可以把一个长字符串写成多行。

Google Style 语法规范中是不推荐这样写的,回忆一下使用什么形式???


Python 中的长字符串

前面提到过,使用三个单引号或者双引号('''...'''"""...""")可以对多行内容进行注释,这其实就是 Python 长字符串的写法。

如果长字符串没有赋值给任何变量,那么这个长字符串就不会起到任何作用,和一段普通的文本无异,相当于被注释掉了。

长字符串的引入可以解决单引号 ' 或双引号 " 使用问题(字符串内部既包含 ' 又包含 ")。

尤其是当程序中有大段文本内容需要定义成字符串时,优先推荐使用长字符串形式,因为这种形式非常强大,可以在字符串中放置任何内容,而且 所见即所得,可以自己试试:

1
2
3
4
5
6
>>> print('''line1
... line2
... line3''')
line1
line2
line3

当然了,长字符串中反斜杠(\)也有转义字符的含义,和在普通字符串的用法是一致的。

–> 最大的好处:

'''...''' 的书写方式让开发人员从 引号和特殊字符串的泥潭 里面解脱出来,自始至终保持一小块字符串(特殊字符串)的格式,即所见即所得(皮卡丘….):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
print('''
へ     /|
  /\7    ∠_/
  / │   / /
 │ Z _,< /   /`ヽ
 │     ヽ   /  〉
  Y     `  /  /
 イ● 、 ●  ⊂⊃〈  /
 ()  へ    | \〈
  >ー 、_  ィ  │ //
  / へ   / ノ<| \\
  ヽ_ノ  (_/  │//
  7       |/
  >―r ̄ ̄`ー―_''')

一个典型的用例是,当你需要一块 HTML 或者 SQL 时,这时用字符串组合,特殊字符串转义将会非常的繁琐。如果你使用长字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
HTML = '''
<HTML><HEAD><TITLE>
Friends CGI Demo</TITLE></HEAD>
<BODY><H3>ERROR</H3>
<B>%s</B><P>
<FORM><INPUT TYPE=button VALUE=Back
ONCLICK="window.history.back()"></FORM>
</BODY></HTML>
'''
cursor.execute('''
CREATE TABLE users (
login VARCHAR(8),
uid INTEGER,
prid INTEGER)
''')

Python 中的原始字符串

在普通字符串或者长字符串的开头加上 r 前缀,就变成了原始字符串,具体格式为:

1
2
str1 = r'原始字符串内容'
str2 = r"""原始字符串内容"""

转义字符 \ 可以用来转义,而使用 r 或(R) 可以让 \ 不发生转义。。 如 r"this is a line with \n" 则 \n 会显示,并不是换行。同理,'''...''' 也可以和 r(R)组合,用于消掉多行字符串中的转义。

普通原始字符串中的引号问题 >>>>>

如果普通格式('...')的原始字符串中出现引号('),同样需要对引号(')进行转义,但是和普通字符串不同的是,此时用于转义的反斜杠(\)会变成字符串内容的一部分:

1
2
3
>>> str1 = r'I\'m a great coder!'
>>> print(str1)
I\'m a great coder!

怎么办??? >>> 使用长字符串

1
2
3
>>> str1 = r'''I'm a great coder!'''
>>> print(str1)

注意,不管是普通字符串还是长字符串,其原始字符串的结尾处不能是反斜杠。为什么?

如果原始字符串的结尾处是反斜杠,那么字符串结尾处的引号会被转义,导致字符串不能正确结束。例如:

1
2
3
# 结尾处的反斜杠都会转移后面的引号
str1 = r'D:\Program Files\Python 3.8\'
str1 = r'''D:\Program Files\Python 3.8\'''

怎么办??? >>>

1
2
3
# 结尾处的反斜杠都会转移后面的引号
str1 = r'D:\Program Files\Python 3.8' + '\\'
str1 = r'''D:\Program Files\Python 3.8''' + '\\'

String 数据类型转化

str(object) 函数可以将 Python 对象(数字、列表、元组、字典、集合等)转化为适于人阅读的形式。

1
2
3
4
5
6
7
8
9
10
11
12
>>> str(True)
'True'
>>> str(123.32)
'123.32'
>>> str([1,2,3,4])
'[1, 2, 3, 4]'
>>> str(("Google","Opera"))
"('Google', 'Opera')"
>>> str({"Google":1,"Opera":2})
"{'Google': 1, 'Opera': 2}"
>>> str({"Google", "Opera"})
"{'Google', 'Opera'}"

哎?!前面我们知道了 Number 数据类型之间的相互转换,并且这里我们也了解了 str(object) 的使用,那么我们可以将字符串类型的数据强制转换成 Number 类型吗?

当然也可以,只是存在一定的限制:

只有 符合整数规范 的字符串类数据,才能被强制转换。

–> 如何理解?以 int() 强制转换字符串为例:

1、整数形式的字符串,比如 ‘6’ 和 ‘1’,可以被 int() 函数强制转换。

2、文字形式,比如中文、火星文或者标点符号,不可以被 int() 函数强制转换。

3、小数形式的字符串,由于 Python 的语法规则,也不能使用 int() 函数强制转换。

比方说下列代码(值异常:浮点类型字符串无法使用 int() 强制转换):

1
2
3
print(int('3.8'))

# 运行后显示结果:ValueError:invalid literal for int() with base 10: '3.8'

你还可以尝试一下其它强制转换函数:float()bool()complex(),这里就不给出样例了。


字符串序列支持

Python 中的字符串是一个不可变序列(Sequence),所以 Python 序列中支持的方法在字符串中都可使用:

【1】 >>>> 字符串索引与切片

Python 中的字符串有两种字符索引方式,从左往右以 0 开始(正向),从右往左以 -1 开始(反向)。可以使用 索引以及方括号 来截取字符串:

1
2
3
4
5
6
7
8
9
10
11
str = 'Welcome to Python world'

print (str) # 输出字符串

# 1. 字符索引:
print (str[0]) # 索引获得字符串第一个字符

# 2. 字符串切片:
print (str[0:-1]) # 输出第一个到倒数第二个的所有字符
print (str[2:5]) # 输出从第三个开始到第五个的字符
print (str[2:]) # 输出从第三个开始的后的所有字符

执行结果如下:

1
2
3
4
5
Welcome to Python world
Welcome to Python worl
W
lco
lcome to Python world

请注意,字符串是不可变类型,故我们不能对索引到的字符串字符进行修改或删除:

1
2
3
4
5
6
7
8
9
10
>>> str = "welcome"
>>> str[2] = '3'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

>>> del str1[2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object doesn't support item deletion

【2】 >>>> 字符串加法(连接)和乘法

1
2
3
4
5
>>> print("that" + "is" + "good")
thisisgood

>>> print("good" * 2)
goodgood

注意,字符串连接符(+)连接的对象只能是字符串,不可以:"123" + 3 or "123445" + [1,2,3] or "123445" + {2:3, 3:4}


【3】 >>>> 字符串成员检查

字符串成员检查就是就是,判断某字符串对象是否包含在另一个字符串对象中,返回的是布尔型值。

可用于判断字符串是否包含某个子串,如下(in && not in):

1
2
3
4
5
6
>>> str1 = "welcome to python world"
>>> substr = "come"
>>> print(substr in str1)
True
>>> print(substr not in str1)
False

【4】 >>>> 字符串长度获取

通过通过 Python 内置函数 len(str) 获取字符串长度

1)len(s)

len()方法返回对象(字符串、列表、元组等)长度或项目个数。

1
2
3
>>>str = "python"
>>> len(str) # 字符串长度
6

【5】 >>>> 取字符串中的最大、小值

使用内置函数:max(str) && min(str)

max() 方法返回字符串中最大的字母。

1
2
3
>>> str = "welcome"
>>> print ("最大字符: " + max(str))
最大字符: w

min() 方法返回字符串中最小的字母。

1
2
3
>>> str = "welcome"
>>> print ("最小字符: " + min(str))
最小字符: c

字符串相关运算

假设实例变量 a 值为字符串 “Hello”,b 变量值为 “Python”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
>>> a = 'Hello'
>>> b = 'Python'

# 字符串连接: `+`
>>> print(a + b)
HelloPython

# 重复输出字符串: `*`
>>> print(a*2)
HelloHello

# 通过索引获取字符串中字符: `[]`
>>> print(a[3])
l

# 截取字符串:`[:]`
>>> print(a[1:3])
el

# 用于判断字符串是否包含某个子串:
# 如果字符串中包含给定的字符返回 True :`in`
>>> print ('H' in a)
True
>>> print ('Hel' in a)
True
# 如果字符串中不包含给定的字符返回 True :`not in`
>>> print ('H' not in a)
False

字符串常用方法整理

这里要注意 ↓↓↓↓↓↓

Python 中的字符串是一个不可变对象,所以所有修改和生成字符串的操作的实现方法,都是在另一个内存片段中生成一个新字符串对象。

例如,'abc'.upper() 将会在划分另一个内存片段,并将返回的 ABC 保存在此内存中。

下面正式开始整理 Python 字符串中的常用方法:

字符串大小写转换

[1] >>>> lower && upper

1
2
str.upper()
str.lower()

str.upper() 内置函数会将字符串中的所有字符都转换为大写;str.lower() 内置函数则将字符串中的所有字符转换为小写。

例如:

1
2
3
4
>>> print('ab XY'.lower())
ab xy
>>> print('ab XY'.upper())
AB XY

[2] >>>> title && capitalize

1
2
str.title()
str.capitalize()

str.title() 内置函数是英文标题式写法,会将字符串所有单词的首字母变成大写,而其他字母依然小写(单词直接可以使用其它非空格连接符);str.capitalize() 内置函数是首字母大写(capitalize 原译),会将字符串首字母大,而其他字母依然小写。

例如:

1
2
3
4
>>> print('ab XY'.title())
Ab Xy
>>> print('abc DE'.capitalize())
Abc de

[3] >>>> swapcase

1
str.swapcase()

str.swapcase() 内置函数是对字符串进行大小写转换(swapcase 原译)。

例如:

1
2
>>> print('abc XYZ'.swapcase())
ABC xyz

isXXX 判断

[1] >>>> isalpha,isdecimal,isdigit,isnumeric,isalnum

1
2
3
4
5
6
str.isdecimal()
str.isdigit()
str.isnumeric()

str.isalpha()
str.isalnum()

分别判断字符串 str 是否是数字、字母、字母或数字组合。

isdecimal,isdigit,isnumeric 均用来判断是否是数字,区别如下:

函数 描述
isdecimal() 是否为十进制数字符,包括 Unicode 数字、双字节全角数字,不包括罗马数字、汉字数字、小数。
isdigit() 是否为数字字符,包括 Unicode 数字,单字节数字,双字节全角数字,不包括汉字数字,罗马数字、小数。
isnumeric() 是否所有字符均为数值字符,包括 Unicode 数字、双字节全角数字、罗马数字、汉字数字,不包括小数。

例如:

1
2
3
4
5
6
>>> print('34'.isdigit())
True
>>> print('abc'.isalpha())
True
>>> print('a34'.isalnum())
True

[2] >>>> islower,isupper,istitle

1
2
3
str.islower()
str.isupper()
str.istitle()

分别判断字符串是否全部小写、全部大写、英文标题式写法。要求 str 中至少要包含一个字母,否则直接返回 False。例如不能是纯数字。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> print('a34'.islower())
True
>>> print('AB'.isupper())
True
>>> print('Aa'.isupper())
False
>>> print('Aa Bc'.istitle())
True
>>> print('Aa_Bc'.istitle())
True
>>> print('Aa bc'.istitle())
False

# 单词使用 `_` 分隔符进行分隔
>>> print('Aa_bc'.istitle())
False

# 下面的返回 False,因为非首字母 C 不是小写
>>> print('Aa BC'.istitle())
False

[3] >>>> isspace,isprintable,isidentifier

1
2
3
str.isspace()
str.isprintable()
str.isidentifier()

分别判断字符串是否是空白(空格、制表符、换行符等)字符,是否是可打印字符(例如制表符、换行符就不是可打印字符,但空格是),是否满足标识符定义规则。

例如:

1)判断是否为空白(没有任何字符是不算是空白):

1
2
3
4
5
6
7
8
9
10
>>> print(' '.isspace())
True
>>> print(' \t'.isspace())
True
>>> print('\n'.isspace())
True
>>> print(''.isspace())
False
>>> print('Aa BC'.isspace())
False

2)判断是否是可打印字符:

1
2
3
4
5
6
7
8
9
10
>>> print('\n'.isprintable())
False
>>> print('\t'.isprintable())
False
>>> print('acd'.isprintable())
True
>>> print(' '.isprintable())
True
>>> print(''.isprintable())
True

3)判断是否满足标识符定义规则(只能是字母或下划线开头、不能包含除数字、字母和下划线以外的任意字符):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> print('abc'.isidentifier())
True
>>> print('2abc'.isidentifier())
False
>>> print('abc2'.isidentifier())
True
>>> print('_abc2'.isidentifier())
True
>>> print('_abc_2'.isidentifier())
True
>>> print('_Abc_2'.isidentifier())
True
>>> print('Abc_2'.isidentifier())
True

字符串填充

[1] >>>> center

1
str.center(width[, fillchar])

将字符串居中,左右两边使用 fillchar(默认为空格) 进行填充,使得整个字符串的长度为 width。如果设置的 width 小于字符串的长度,则无法填充直接返回字符串本身(不会创建新字符串对象)。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
>>> print('ab'.center(4,'_'))
_ab_
>>> print('ab'.center(5,'_'))
__ab_

>>> print('ab'.center(4))
ab
>>> print(len('ab'.center(4)))
4

>>> print('abcde'.center(3))
abcde

[2] >>>> ljust && rjust

1
2
str.ljust(width[, fillchar])
str.rjust(width[, fillchar])

ljust() 函数使用 fillchar 填充在字符串 str 的右边,使得整体长度为 widthrjust() 函数则是填充在左边。

如果不指定 fillchar,则默认使用空格填充。如果 width 小于或等于字符串 str 的长度,则无法填充,直接返回字符串本身(不会创建新字符串对象)。

例如:

1
2
3
4
>>> print('xyz'.ljust(5,'_'))
xyz__
>>> print('xyz'.rjust(5,'_'))
__xyz

[3] >>>> zfill

1
str.zfill(width)

zero fill 默认在字符串 str 的左边用 0 填充使其长度为 width。如果 str 前有正负号 +/-,则 0 填充在 +/- 符号后面,且符号也算入长度。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> print('abc'.zfill(5))
00abc

>>> print('-abc'.zfill(5))
-0abc

>>> print('+abc'.zfill(5))
+0abc

>>> print('42'.zfill(5))
00042

>>> print('-42'.zfill(5))
-0042

>>> print('+42'.zfill(5))
+0042

子串搜索

[1] >>>> count

1
str.count(sub[, start[, end]])

count 方法用于统计字符串里某个子串出现的次数。可选参数为在字符串搜索的开始与结束位置:

  • sub – 搜索的子字符串
  • start – 字符串开始搜索的位置。默认为第一个字符,第一个字符索引值为0。
  • end – 字符串中结束搜索的位置。字符中第一个字符的索引为 0。默认为字符串的最后一个位置。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> print('xyabxyxy'.count('xy'))
3

# 次数2,因为从 index=1 算起,即从 'y' 开始查找,查找的范围为 'yabxyxy'
>>> print('xyabxyxy'.count('xy',1))
2

# 次数1,因为不包括 end,所以查找的范围为 'yabxyx'
>>> print('xyabxyxy'.count('xy',1,7))
1

# 次数2,因为查找的范围为 'yabxyxy'
>>> print('xyabxyxy'.count('xy',1,8))
2

[2] >>>> endswith,startswith

1
2
str.endswith(suffix[, start[, end]])
str.startswith(prefix[, start[, end]])

endswith() 函数检查字符串 str 是否以 suffix 结尾,返回布尔值的 TrueFalsesuffix 可以是一个元组(tuple)。可以指定起始 start 和结尾 end 的搜索边界。同理,startswith() 用来判断字符串 str 是否是以 prefix 开头。

例如(startswith 和 endswith 用法相同):

1)suffix 是普通的字符串时:

1
2
3
4
5
6
7
8
9
10
11
12
>>> print('abcxyz'.endswith('xyz'))
True
 
# False,因为搜索范围为'yz'
>>> print('abcxyz'.endswith('xyz',4))
False
 
# False,因为搜索范围为'abcxy'
>>> print('abcxyz'.endswith('xyz',0,5))
False
>>> print('abcxyz'.endswith('xyz',0,6))
True

2)suffix 是元组(tuple)时(只要 tuple 中任意一个元素满足 endswith 的条件,就返回 True):

1
2
3
4
5
6
7
8
9
10
11
# tuple中的'xyz'满足条件
>>> print('abcxyz'.endswith(('ab','xyz')))
True
 
# tuple中'ab''xy'都不满足条件
>>> print('abcxyz'.endswith(('ab','xy')))
False
 
# tuple中的'z'满足条件
>>> print('abcxyz'.endswith(('ab','xy','z')))
True

[3] >>>> find,rfind && index,rindex

1
2
3
4
str.find(sub[, start[, end]])
str.rfind(sub[, start[, end]])
str.index(sub[, start[, end]])
str.rindex(sub[, start[, end]])

find() 搜索字符串 str 中是否包含子串 sub。如果包含,则返回 sub 的索引位置,否则返回 -1。可以指定起始 start 和结束 end 的搜索位置。而 index()find() 一样,唯一不同点在于当找不到子串时,抛出 ValueError 错误。

rfind()rindex() 是搜索最右边子串的位置,如果有返回索引位置,没有则返回 -1ValueError 错误。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> print('abcxyzXY'.find('xy'))
3
>>> print('abcxyzXY'.find('Xy'))
-1
>>> print('abcxyzXY'.find('xy',4))
-1

>>> print('xyzabcabc'.find('bc'))
4
>>> print('xyzabcabc'.rfind('bc'))
7

>>> print('xyzabcabc'.rindex('bcd'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: substring not found

字符串替换

[1] >>>> replace

1
str.replace(old, new[, count])

将字符串中的子串 old 替换为 new 字符串。如果给定 count,则表示只替换前 countold 子串。如果 str 中搜索不到子串 old,则直接返回字符串本身(不创建新字符串对象)。

[2] >>>> maketrans && translate

1
2
str.translate(table)
static str.maketrans(x[, y[, z]])

str.maketrans() && translate(table) 是需要配合使用的。str.maketrans() 函数会生成一个字符一一映射的 table(字符映射转换表,然后 translate(table) 使用字符映射转换表,转换字符串 str 中的字符。

例如:想要对 “I love Fairy” 做一个简单的加密,将里面部分字符(使用字符映射转换表)都替换为数字,这样别人就不知道转换后的这句话是什么意思。

1
2
3
4
5
6
7
8
9
10
11
12
>> in_str='abcxyz'
>>> out_str='123456'

# maketrans()生成映射表
>>> map_table=str.maketrans(in_str,out_str)

# 使用translate()进行映射
>>> my_love='I love Fairy'
>>> result=my_love.translate(map_table)

>>> print(result)
I love F1ir5

注意,maketrans(x[, y[, z]]) 中的 xy 都是字符串,且长度必须相等。如果 maketrans(x[, y[, z]]) 给定了第三个参数 z,则这个参数字符串(z)中的每个字符都会被映射为 None。

1
2
3
4
5
6
7
8
>>> in_str='abcxyz'
>>> out_str='123456'
>>> map_table=str.maketrans(in_str,out_str,'ay')
>>> my_love='I love Fairy'
>>> result=my_love.translate(map_table)

>>> print(result)
I love Fir

字符串分割

[1] >>>> split,rsplit && splitlines

1
2
3
str.split(sep=None, maxsplit=-1)
str.rsplit(sep=None, maxsplit=-1)
str.splitlines([keepends=True])

三者都是用来分割字符串,并生成一个列表。

split() 会根据指定的 sep 分隔符来对 str 进行分割,maxsplit 用于指定最大分割次数,如果不指定 maxsplit 或者给定值为 -1,则会从左向右搜索并且每遇到 sep 一次就分割直到搜索完字符串。如果不指定 sep 或者指定为 None,则改变分割算法:以空格为分隔符,且将连续的空白压缩为一个空格。rsplit()split() 是一样的,只不过是从右边向左边搜索。

1
2
3
4
5
6
7
>>> str = "this is string example....!!!"
>>> print (str.split( )) # 以空格为分隔符
['this', 'is', 'string', 'example....!!!']
>>> print (str.split(' ',1)) # 以空格为分隔符
['this', 'is string example....!!!']
>>> print (str.split('i')) # 以 i 为分隔符
['th', 's ', 's str', 'ng example....!!!']

splitlines() 可以按照字符串中的换行符 ('\r', '\r\n', \n') 对字符串进行分隔,返回一个包含各行作为元素的列表。如果参数 keependsFalse,不包含换行符(默认);如果为 True,则保留换行符。

1
2
3
4
5
6
>>> 'ab c\n\nde fg\rkl\r\n'.splitlines()
['ab c', '', 'de fg', 'kl']
>>> 'ab c\n\nde fg\rkl\r\n'.splitlines(False)
['ab c', '', 'de fg', 'kl']
>>> 'ab c\n\nde fg\rkl\r\n'.splitlines(True)
['ab c\n', '\n', 'de fg\r', 'kl\r\n']

[2] >>>> partition,rpartition

1
2
str.partition(sep)
str.rpartition(sep)

搜索字符串 str 中的是否含有子串 sep,并从 sep 处对 str 进行分割,最后返回一个包含 3 个元素的元组:sep 左边的部分是元组的第一个元素,sep 自身是元组的二个元素,sep 右边是元组的第三个元素。

partition(sep) 从左边第一个 sep 进行分割,rpartition(sep) 从右边第一个 sep 进行分割。如果搜索不到 sep,则返回的 3 元素元组中,有两个元素为空。partition() 是后两个元素为空,rpartition() 是前两个元素为空。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 只搜索到一个 sep 时,两者结果相同
>>> print('abcxyzopq'.partition('xy'))
('abc', 'xy', 'zopq')
>>> print('abcxyzopq'.rpartition('xy'))
('abc', 'xy', 'zopq')

# 搜索到多个 sep 时,分别从左第一个、右第一个 sep 分割
>>> print('abcxyzxyopq'.partition('xy'))
('abc', 'xy', 'zxyopq')
>>> print('abcxyzxyopq'.rpartition('xy'))
('abcxyz', 'xy', 'opq')

# 搜索不到 sep
>>> print('abcxyzxyopq'.partition('xyc'))
('abcxyzxyopq', '', '')
>>> print('abcxyzxyopq'.rpartition('xyc'))
('', '', 'abcxyzxyopq')

join
1
str.join(iterable)

将可迭代对象(iterable)中的元素使用 ste 连接起来。注意,iterable 中必须全部是字符串类型,否则报错。

如果你还是 Python 的初学者,还不知道 iterable 是什么,你可以暂时将它理解为:字符串 string、列表 list、元组 tuple、字典 dict、集合 set。

例如:

1)字符串:

1
2
3
>>> L='python'
>>> '_'.join(L)
'p_y_t_h_o_n'

2)元组:

1
2
3
>>> L1=('1','2','3')
>>> '_'.join(L1)
'1_2_3'

3)集合(无序):

1
2
3
>>> L2={'p','y','t','h','o','n'}
>>> '_'.join(L2)
'n_o_p_h_y_t'

4)列表:

1
2
3
>>> L2=['py','th','o','n']
>>> '_'.join(L2)
'py_th_o_n'

5)字典:

1
2
3
>>> L3={'name':"malongshuai",'gender':'male','from':'China','age':18}
>>> '_'.join(L3)
'name_gender_from_age

6)iterable 参与迭代的每个元素必须是字符串类型,不能包含数字或其他类型:

1
2
3
4
5
6
7
8
>>> L1=(1,2,3)
>>> '_'.join(L1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sequence item 0: expected str instance, int found

>>> L1=('ab',2)
>>> L2=('AB',{'a','cd'})

7)join() 时的元素连接符指定为空(””)时,则会将可迭代对象的每个元素组成一个连接起来的字符串。有时候,这是很有用的:

1
2
3
>>> L=['a','b','c','d']
>>> ''.join(L)
'abcd'

字符串修剪
1
2
3
str.strip([chars])
str.lstrip([chars])
str.rstrip([chars])

分别是移除左右两边、左边、右边的字符 char。如果不指定 chars 或者指定为 None,则默认移除空白(空格、制表符、换行符)。

lstrip([chars])方法用于截掉字符串左边的 指定字符(默认为:空格'Tab'\n)或指定字符。

1
2
3
4
5
6
7
8
>>> str = "   !!!this is string example....!!!   \n";
>>> print(str)
!!!this is string example....!!!

>>> print( str.lstrip() );
!!!this is string example....!!!

>>>

rstrip([chars])方法用于截掉字符串左边的 指定字符(默认为空格、\n)或指定字符。

1
2
3
>>> print( str.rstrip() );
!!!this is string example....!!!
>>>

strip(chars) 方法用于移除字符串头尾 指定的字符(默认为空格、\n)或字符序列。

1
2
>>> print( str.strip() );
!!!this is string example....!!!

字符串编码 && 解码

str.encode(encoding=’UTF-8’,errors=’strict’) && bytes.decode(encoding=”utf-8”, errors=”strict”)

str.encode() 会以 encoding 指定的编码格式编码字符串。

errors 参数用于设置不同错误的处理方案。默认为 strict,意为解码错误引起一个 UnicodeError。其他可能得值有 ignore, replace, xmlcharrefreplace, backslashreplace 以及通过 codecs.register_error() 注册的任何值。

Python3 中没有 str decode 方法,这是合理的,编码之后 Python 字符串已经变成了一个 bytes 字节串了。所以我们可以使用 bytes 对象的 bytes.decode() 方法来解码给定的 bytes 对象,这个 bytes 对象可以由 str.encode() 来编码返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> str = "我想学中文";
>>> help(str.encode)
>>> str_utf8 = str.encode("UTF-8")
>>> str_gbk = str.encode("GBK")

>>> print(str)
我想学中文

>>> print("UTF-8 编码:", str_utf8)
UTF-8 编码: b'\xe6\x88\x91\xe6\x83\xb3\xe5\xad\xa6\xe4\xb8\xad\xe6\x96\x87'
>>> print("GBK 编码:", str_gbk)

>>> help(bytes.decode)

GBK 编码: b'\xce\xd2\xcf\xeb\xd1\xa7\xd6\xd0\xce\xc4'
>>> print("UTF-8 解码:", str_utf8.decode('UTF-8','strict'))
UTF-8 解码: 我想学中文
>>> print("GBK 解码:", str_gbk.decode('GBK','strict'))
GBK 解码: 我想学中文

字符串格式化

字符串格式化涉及到的内容较多,考虑到篇幅原因我们在 Python 字符串之格式化输出 一文中进行了详细说明。这里是为了保持字符串章节完整性故设立一个链接模块。


字符串编码

关于 Python 字符串编码涉及到的内容较多,考虑到篇幅原因我们在 Python 字符串之 Unicode 编码 一文中进行了详细说明。这里是为了保持字符串章节完整性故设立一个链接模块。


Python 中的序列

开始学习元组(Tuple)和列表(List)之前,推荐先了解 Python 中的序列概念。篇幅原因,该部分内容请转至系列教程:Python 中的序列


Author

Waldeinsamkeit

Posted on

2018-01-05

Updated on

2022-11-07

Licensed under

You need to set install_url to use ShareThis. Please set it in _config.yml.

Comments

You forgot to set the shortname for Disqus. Please set it in _config.yml.