Python基础手册P2 基本数据类型基本类型
Python 基本数据类型
。。。
今天没有想要写在开头的废话,,,好烦,要不破例直接开始吧。
变量与常量
变量
Python 是一门动态语言,这意味着 Python 变量本身的类型是不固定的。
在 Python 中使用变量前不用声明(不用写类似 int a; 的语句),在首次使用前为其赋初始值就行(直接用 a = 0)。
常量
实际上,在 Python 语法中并没有定义常量。
但是 PEP 8 定义了常量的命名规范为大写字母和下划线组成。在实际应用中,这种“常量”首次赋值后,无法阻止其他代码对其进行修改或删除。
要使用真正的常量,可以自己实现一个,例如:constants-in-python。
空值
Python 中使用 None 来代表空值。None 在交互式命令行中不会显示,但可以用 print() 打印出来:
1 | None |
布尔值
Python 中有布尔值 True 和 False。
真值问题
代表 ‘假’ 的值有:False,None,0,'',[],{},…;
其余值为真。
布尔值的相关的运算
| 逻辑运算符 | 相当于C中的 |
|---|---|
and |
&& |
or |
` |
not |
! |
⚠️【注意 and 的优先级高于 or。
| 比较运算符 |
|---|
<, >, ==, != |
使用比较运算符得到的结果是布尔值(True 或 False)。
使用逻辑运算符得到的结果未必是布尔值:
具体的运算情况可以参考下面这段程序生成的表:
1 | # **注意,是第一列的值 and|or 第一行的值!** |
从中可以看到,and 的规则是:
前后两者 皆为真 ,返回 后 者;
前后两者 有一假 ,返回 假 者;
前后两者 皆为假 ,返回 前 者;
or 的规则是:
前后两者 皆为真 ,返回 前 者;
前后两者 有一真 ,返回 真 者;
前后两者 皆为假 ,返回 后 者;
此外,not 的规则是:
若对象为 真 ,返回
False
若对象为 假 ,返回True
数字
int, float
| 数字 | 含义 | 表示范围 | 精度 |
|---|---|---|---|
| int | 整数 | 大小没有限制 | 始终是准确的 |
| float | (基于二进制的)浮点数 | 有一定大小限制,超出后表示为inf | 和C一样,不准确 |
复数
Python 还内置了对 复数 的支持,使用后缀 j 或 J 表示虚数部分(例如,3+5j)。
1 | a = 3 + 1j |
关于这部分详见官方文档。
其他数字类型
在标准库中,python 还有对 精确小数 Decimal(基于十进制的浮点数)和 分数 Fraction 等其他数字类型的支持。
Decimal (小数)
在 Python 的标准库中,decimal 库提供了 基于十进制的浮点数 Decimal 类型,这种数字类型修复了 float 的不准确问题,可以用 Decimal 实现更加精准的数学计算(但也不是绝对的准确,仍存在误差)。
1 | from decimal import * |
正如上例,要使用 Decimal 类型,
首先要
import decimal;然后用
decimal.Decimal(Num)来获取一个 Decimal 实例,这里的 Num 可以是如下几种:1
2
3
4
5
6
7
8
9
10Decimal('3.14') # 内容是 float 的字符串
Decimal('3.14')
Decimal((0, (3, 1, 4), -2)) # tuple (sign, digit_tuple, exponent),得到的值是 (-1) * sign * digit_tuple 代表数字 * 10 ^ exponent
Decimal('3.14')
Decimal(314) # int,float 都可以
Decimal('314')
Decimal(Decimal(314)) # 另一个 decimal 实例
Decimal('314')
Decimal(' 3.14 \\n') # 前后可以有空白字符
Decimal('3.14')decimal.getcontext().prec 代表有效位数,
- 通过
print(decimal.getcontext().prec)来查看当前值,默认是28位 - 通过
decimal.getcontext().prec = Places来设置有效位数,这个精度的取值是[1, MAX_PREC],MAX_PREC取值在64位机器上是999999999999999999,32位为425000000(这是因为这个值要可以转化为C的整型,详见Python版的源码)!
- 通过
加减乘除运算入常
Fraction (分数)
在 fractions 库中,定义了 Fraction 类型,用以表达分数,加减乘除运算入常。
使用方法如下:
1 | from fractions import * |
字符串
字符串的表示
Python 中,字符串可以用单引号 ('...') 或双引号 ("...") 标识单行内的字符串,
还可以使用连续三个单/双引号('''...''' 或 """...""")表示与格式化的多行字符。
Python没有单独的字符类型;一个字符就是一个简单的长度为1的字符串。
1 | st = '1\ |
⚠️【注意】单引号可以包含双引号,'asd"123"fgh' 是允许的,同样 ''' 中也可以包含 """。
字符编码
首先,附上几种字符编码的比较:
| 编码 | 长度 | ‘A’ | ‘中’ |
| – | – | – | – |
| ASCII | 1 Byte | 01000001 | (无此字符) |
| Unicode | 通常是2 Byte | 00000000 01000001 (ASCII前补零) | 01001110 00101101 |
| UTF-8 | 可变(1~6 Byte)| 01000001 (UTF-8包含着ASCII)| 11100100 10111000 10101101 |
Python3.x 默认用 Unicode 编码字符串。
编码 <=> 字符 的函数:
ord():获取字符的整数表示;chr():把编码转换成对应的字符;
例如:
1 | ord('A') |
Python 的字符串类型是 str。
str在内存中以 Unicode 表示,一个字符对应若干字节。
在写入二级缓存(本地->硬盘 | 远程->网络)时,str将变为bytes。
bytes以字节为单位。
Python 用带 b 前缀的单/双引号表示 bytes。
| str | bytes |
|---|---|
'ABC' |
b'ABC' |
str <=> bytes:
- encode(): str –> bytes
1 | 'abc'.encode('ascii') |
- decode(): bytes –> str
1 | b'abc'.decode('ascii') |
⚠️【注意】为避免乱码问题,应始终使用 utf-8 编码对 str 和 bytes 进行转换。
转义字符
Python 字符串中可以使用转义字符,可以参考下表:
| 转义字符 | 描述 |
|---|---|
\(在行尾时) |
续行符 |
\\ |
反斜杠符号 |
\' |
单引号 |
\" |
双引号 |
\a |
响铃 |
\b |
退格(Backspace) |
\e |
转义 |
\000 |
空 |
\n |
换行 |
\v |
纵向制表符 |
\t |
横向制表符 |
\r |
回车 |
\f |
换页 |
\xxx |
八进制数,例如:'\100' 代表 '@' |
\oyy |
八进制数,yy代表的字符,例如:'\o12' 代表换行 |
\xyy |
十六进制数,yy代表的字符,例如:'\x0a' 代表换行 |
\uxxxx |
十六进制数,xxxx代表的字符,例如:'\u4e2d\u6587' 代表 '中文' |
\other |
其它的字符以普通格式输出,例如:'\sds' 代表 '\\sds' |
若要取消转义,可以给字符串 r 前缀:
1 | print('C:\some\name') # here \n means newline! |
基本字符串操作
获取字符串长度
Python 内置的 len() 函数可以获取多种类型的对象长度,包括字符串。
1 | len(word) |
字符串连接
- 相邻的两个字符串文本自动连接在一起。
1 | 'Py' 'thon' |
- 字符串的
+与*
字符串可以由 + 操作符连接(粘到一起),可以由 * 表示重复。
1 | # 3 times 'un', followed by 'ium' |
字符串插值
字符串的插值主要有 4 种方式:
- 字符串连接
1 | a = 123 |
%元组插值
1 | a = 123 |
- 字符串的
format方法
1 | 'a = {arg_a}, b = {arg_b}, c = {arg_c}'.format(arg_a="东方", arg_b=123, arg_c=333.44+8j) |
或者也可以匿名:
1 | 'Another way: {0}, {2}, {1}, {3}'.format("zero", 2, 1.0, 3) |
f-string
Python 3.6 引入了 f-string,让插值更加优雅:
1 | a = 123 |
更多关于 f-string 的说明,可以参考 realpython的这篇文章,或者查看 f-string 的来源:PEP 498 – Literal String Interpolation。
字符串切分
用字符串的 split 方法可以以指定字符串为分割切分字符串:
1 | 'a b c'.split(' ') |
字符串替换
用字符串的 replace 方法可以替换字符串的一部分:
1 | 'he-*-ll-*-o--'.replace('-*-', '...') |
字符串索引及切片
- 索引
| 字符 | P | y | t | h | o | n |
|---|---|---|---|---|---|---|
| 正向索引 | 0(-0) | 1 | 2 | 3 | 4 | 5 |
| 反向索引 | -6 | -5 | -4 | -3 | -2 | -1 |
1 | word = 'Python' |
- 切片
索引用于获得单个字符,切片 让你获得一个子字符串。
切片的规则是:str[起始:末尾:间隔]
* 起始:开始的索引(取),缺省为0
* 末尾:结束的索引(不取),缺省时,取到字符串最后一个字符(取得到)
* 间隔:每取一个之后间隔几个(>0),缺省为1,为负值时倒着取
1 | word[0:2] # characters from position 0 (included) to 2 (excluded) |
⚠️【注意】切片包含起始的字符,不包含末尾的字符。s[:i] + s[i:] == s
⚠️【注意】字符串索引、切片都是只读的,不可以给字符串索引、切片赋值!
正则表达式
字符串的使用肯定绕不过正则表达式,python 内置了正则表达式模块—— re 。
我不在这里介绍正则表达式的写法,只是展示怎么用 Python 完成常见的正则表达式操作。正则本身有问题,请到 https://regexr.com。
匹配:
1 | import re |
提取:
1 | import re |
用 m.groups() 即可获取提取到的组:('123', '456')。
切分:
1 | # 切分 |
集合类型
其实,在我心中,字符串也是种集合类型(你学过C语言就会有同感了,字符串不过是字符组成的 list 而已)。所以,刚才介绍字符串的很多操作,在接下来的 list 中也一样适用。
list
list:列表,写在 [] 中。
1 | l0 = [] |
索引&切片:
- get:
lst[索引 || 切片] - set:
lst[索引 || 切片] = 值
1 | >>> l[0] = 3.14 |
索引&切片 和字符串中介绍的相同,不了解可以这回去看。
我们来看 list 的基本操作:
尾部添加:lst.append(值), lst.extend(iterable)
1 | l = [] |
append 和 extend 一个是添加单个元素,一个是添加一系列元素。
利用切片,append 方法就等效于 lst[len(lst):] = [值], 而 extend 即 lst[len(lst):] = iterable。
插入:lst.insert(索引, 值)
1 | l = [] |
删:lst.remove(值), lst.pop(索引), clear()
remove 是删除 list 中存在的一个值,若不存在,会报 ValueError。
pop 是删除 list 中给定索引处的值,若索引越界,会报 IndexError。
clear 就是清空(删除)所有元素;也可以用 del a[:] 完成类似的操作。
1 | l |
其他操作:
list.index(x[, start[, end]]): 你给值,它返索引list.count(x): 你给值,它告诉你有几个list.sort(key=None, reverse=False): 一种比较快的原址排序list.reverse(): 列表反转,调个个(这个词好怪a,我的问题嘛?)list.copy(): 返一个自己的浅拷贝。
关于 list ,可以写的东西实在太多了,都可以单独再写一篇,专门研究了。。。(以后再说吧,可能我会写吧,用了复习数据结构课。)
tuple
tuple:元组,和 list 类似,只是常写在 () 中。
tuple 可以 get,不能set。也就是说,不能 append、不能 pop、不能索引赋值。
1 | t = (1,2,3) |
注意,刚才我写了一句“tuple常写在()中”,何来此“常”,tuple 不就是写在圆括号里的嘛?如果你有此疑问,一定是没有好好读过文档。
给你个改过自新的机会:https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences:

文档里写了:
A tuple consists of a number of values separated by commas.
意思是说:“元组(tuple)是一系列用逗号分开的值!”,可没提用圆括号扩起来的呀,再看看这个例子:
1 | t = 12345, 54321, 'hello!' |
可见,tuple 对 Python 中例如函数参数的一系列元素的打包传递相当有用!
set
set 是保证元素唯一的无序集合。
我们一般也就用它来消除重复,保证唯一。当然,你应该知道,set 就大概对应于数学里的「集合」,所以 set 可以算 病娇茶部 并、交、差、补(你可以想象,数学那种补是不能算的,但可以算「对称差」)。
创建一个 set 有两种写法:set() 函数和使用花括号 {ele1, ele2, ...}。但如果你要建空 set,只能用 set(),而不能用 {}!因为你应该知道,{} 建的是空字典。
1 | s = {} |
1 | a |
dict
dict:字典,键值对,底层实现是哈希表。字面值写作 {key1: value1, key2: value2, ...}。
既然 dict 都写成和 set 一样的 {} 了,那你看可以想象,dict 也可以保证唯一性 —— dict保证 key 的唯一。
key 可以是任何「不可变」的值,也就是说,数字、字符串、不包含可变元素的元组都可以作为 key。
1 | d = {1: 'abc', '2': 2.0001} |
1 | tel = {'jack': 4098, 'sape': 4139} |
用 dict() 函数可以有更多初始化字典的技巧,我随便从文档抄两个,你细品:
1 | dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) |
推导式
推导式(comprehensions)是用来创建集合类型实例的。
比如,你想建一个“1到10的平方组成的list”,你如何来写代码?
当然,数据量不大,我们肯定可以这样:
1 | a = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] |
但如果是1~100,1~100000呢?你想用循环对吧:
1 | a = [] |
但这样不够简洁!
“1到10的平方组成的list”,说起来就一句话,代码也应该简简单单一行就完成!「推导式」就是干这个的:
1 | [x**2 for x in range(1, 11)] |
推导式的一般形式是:
1 | [表达式 任意个for或if句] |
这个例子可以给你个比较好的印象:
1 | [(x, y, x*y) for x in [1,2,3] for y in [3,1,4] if x != y] |
其实准确的说,我们刚才写的这些都是「列表推导式」。我们还有「set推导式」甚至是「dict推导式」。
1 | {x for x in 'abracadabra' if x not in 'abc'} |
你可能还想写这个:
1 | (x**2 for x in range(1, 11)) |
哈哈,有点不一样了,这次它给你返了个 generator——生成器,这就不是推导式了,这里不做介绍,后面我们再讨论这东西。
最后,再看两个很有意思的例子:
1 | [[(j, i, j*i) for j in range(1, i+1)] for i in range(1, 10)] |
乘法表,这两种写法效果是一样的。
1 | matrix = [ |
没错!矩阵转置,利用推导式中只用一行代码就可以实现。
未完待续…
(最近这两天都在补作业呀、补作业呀、补作业呀…不补作业的时候还要打游戏…忙得很。而且最近练习双拼,中文打字速度直线下降,所以这篇写了好久。现在作业大概补完了,双拼也已有了小成(大概?),以后应该会快一些了。)
Next: 【Python流程控制】