03. Python 数据类型和运算符

整数类型

4 种进制表示形式

  • 十进制:99, -217
  • 二进制,以 0b 或 0B 开头:0b010, -0B101
  • 八进制,以 0o 或 0O开头:0o123, -0O456
  • 十六进制,以 0x 或 0X 开头:0x9a, -0X89

浮点数类型

与数学中实数的概念一致

  • 带有小数点及小数的数字
  • 浮点数取值范围和小数精度都存在限制,但常规计算可忽略
  • 取值范围数量级约 -10 的 308 次方 至 10 的 308 次方 ,精度数量级 10 的 -16 次方

浮点数间运算存在不确定尾数,不是 bug。和其他编程语言一样,用有限表示无限,只能近似做到。

解决办法: 使用 round 函数
浮点数间运算存在不确定尾数

0.1 + 0.2 == 0.3 结果为 False,但是 round(0.1 + 0.2, 1) == 0.3 的结果为 True。我们在判断的时候有一个技巧。可以 0.1 + 0.2 - 0.3 < 0.00001,其结果也为 True。

round(x, d):对 x 四舍五入,d 是小数截取位数

  • 浮点数间运算及比较用 round()函数辅助
  • 不确定尾数一般发生在 10 -16 左右,round 函数十分有效
1
2
3
4
5
import math

x = 12.3
math.ceil(x) # 向上取整 结果为 13
math.floor() # 向下取整 结果为 12

小知识:“CPython 实现只缓存 ‐5 到 256(含)的整数;id() 在 CPython 可视为地址”。

科学计数法表示

  • 使用字母 e 或 E 作为幂的符号,以 10 为基数,格式如下:
  • <a>e<b> 表示 a*10 b
  • 例如:4.3e-3 值为0.0043 9.6E5 值为 960000.0

复数类型

z = 1.23e - 4 + 5.6e + 89j

  • z.real 获得实部
  • z.imag 获得虚部

数值运算操作符

数字类型的关系

类型间可进行混合运算,生成结果为"最宽"类型

三种类型存在一种逐渐"扩展"或"变宽"的关系:整数 -> 浮点数 -> 复数

例如:123 + 4.0 = 127.0 (整数+浮点数 = 浮点数)

数值运算函数

字符串类型及操作

字符串的序号

使用 [] 获取字符串中一个或多个字符

  • 索引:返回字符串中单个字符 <字符串>[M]
  • 切片:返回字符串中一段字符子串 <字符串>[M:N:step] 注意:这里含头不含尾。step 间隔个数,默认为 1。

字符串反转 <字符串>[::-1]

字符串的特殊字符

  • 转义符表达特定字符的本意
    " 这里有个双引号(")" 结果为 这里有个双引号(")
  • 转义符形成一些组合,表达一些不可打印的含义
    "\b"回退 "\n"换行(光标移动到下行首) “\r” 回车(光标移动到本行首)
  • x + y 两个字符串 x 和 y 的拼接
  • n * x 或者 x * n 复制 n 次字符串 x
  • x in s 如果 x 是 s 的字串则返回 True,否则为 False

一些以函数形式提供的字符串处理功能

Unicode 编码

  • 统一字符编码,即覆盖几乎所有字符的编码方式
  • 从 0 到 1114111 (0x10FFFF)空间,每个编码对应一个字符
  • Python 字符串中每个字符都是 Unicode 编码字符

使用 string 的 format 函数常用到中文空格’ ', 它的 Unicode 的十六进制形式为为 hex3000, 十进制形式为 dec12288, 在 python 的3.x平台可以表示为 chr(12288)

字符串处理方法

字符串类型的格式化

% 字符串格式化(旧式)

语法:'格式串' % 值元组/字典
常用占位符

  • %s 字符串(万能)
  • %d 十进制整数
  • %f 浮点(%.2f 保留两位小数)
  • %x/%X 十六进制

示例

1
2
name = 'Bob'; age = 18
print('Hello %s, you are %d' % (name, age))

注:f-string(3.6+)与 str.format 已逐步替代 %,但 % 仍广泛用于日志/旧代码。

str.format——兼容旧版本

用 {} 占位,再调用 .format(*args, **kwargs) 映射:

字符串格式化使用.format()方法,用法如下:

<模板字符串>.format(<逗号分隔的参数>)

1
2
"Hello {}, you are {:d}".format(name, age)
"Price: {p:.2f} ¥".format(p=9.9)

f-string(3.6+)——最快最简洁

在字符串前加 fF,把变量/表达式直接写进 {}

1
2
name = "Bob"; age = 18
s = f"Hello {name.upper()}, next year {age + 1}."

可带格式说明符:{value:格式}

{pi:.2f} 保留 2 位小数;{n:08b} 补零 8 位二进制。

类型转换

  • bool(xxx)
  • int(n, radix) 分别用于使用类型转成 int 和 int(s, radix) 参数为字符串 和 进制位
  • float(xxx)
  • str(xxx)

运算符简介

算数运算符

运算符 描述 举例
+ 返回两个数相加的结果,例如: 10 + 20 = 30
- 返回两个数相减的结果,例如 :10 - 20 = -10
* 返回两个数相乘的结果,例如: 10 * 20 = 200
/ 返回两个数相除的结果,例如: 10 / 20 = 0.5
// 整除 返回两个数相除,商的整数部分,例如:9 // 2 = 4
% 取余 返回除法运算的余数,例如:9 % 7 = 2
** 指数 返回指数运算结果,例如:2 ** 3 = 8

赋值运算符

赋值运算符就是用来给变量赋值的。

运算符 描述 举例
= 赋值运算符 就是把 = 右边的值赋值给左边的变量,之前用过了。

除了赋值运算符,下面还有复合赋值运算符。

复合赋值运算符就是经过计算后,将值赋给前面的变量。

运算符 描述 举例
+= 加法赋值运算符 c += a 等效于 c = c + a
-= 减法赋值运算符 c -= a 等效于 c = c - a
*= 乘法赋值运算符 c *= a 等效于 c = c * a
/= 除法赋值运算符 c /= a 等效于 c = c / a
%= 取模赋值运算符 c %= a 等效于 c = c % a
**= 赋值运算符 c **= a 等效于 c = c ** a
//= 取整赋值运算符 c //= a 等效于 c = c // a

关系运算符

关系运算符也就是比较运算符,主要有以下几种:

运算符 > < >= <= == !=
含义 大于 小于 大于等于 小于等于 等于 不等于

逻辑运算符

逻辑运算是用来同时判断多个条件。

主要有以下三种:

  • and 与,两边条件同时满足
  • or 或,两边条件满足一个即可
  • not 非,不满足

优先级是 or < and < not,三者全是左结合(从左往右算)。

举例

1
2
not a and b or c       # 等价于  ((not a) and b) or c
a or b and c or d # 等价于 (a or (b and c)) or d

位运算符一览(仅适用于 int / bool)

运算符 名称 作用(按二进制位) 示例
& 按位与 两位都为 1 得 1,否则 0 5 & 31
| 按位或 任一位 1 得 1 5 | 37
^ 按位异或 不同得 1,相同得 0 5 ^ 36
~ 按位取反 一元运算,~x = -(x+1) ~5-6
<< 左移 整体左移 n 位,低位补 0 5 << 220
>> 右移 整体右移 n 位,高位补符号位 -8 >> 2-2

补充规则

  1. 操作数为 bool 时先转 intTrue→1False→0)。
  2. 负数用补码表示,右移保持符号(算术右移)。
  3. 优先级(高→低):~<< >>&^|;建议显式括号。

成员运算符(Membership Operators)

运算符 描述 示例 结果
in 若在指定序列/集合中找到值返回 True 'a' in 'abc' True
not in 若在指定序列/集合中找到值返回 True 4 not in [1,2,3] True
  • 适用对象:字符串、列表、元组、字典、集合、range 等可迭代对象。
  • 字典默认检查而非值;想查值用 value in d.values()
  • 优先级:与 == 同一档,低于算术/位运算,高于逻辑 and/or

身份运算符(Identity Operators)

运算符 描述 示例 结果
is 左右两边是同一对象(id 相等)返回 True x is y 视对象而定
is not 左右两边不是同一对象返回 True x is not y 视对象而定

要点

  1. 比较的是内存身份(id),而非值相等。
  2. 小整数/字符串驻留等缓存机制会让不同变量 isTrue
  3. == 区别:== 调对象的 __eq__ 比较值;is 永远只比较 id。
  4. 单例判断(如 x is None)推荐用 is,速度快且语义清晰。

优先级:与 in 同一档,低于算术/位运算,高于逻辑 and/or

Python 运算符优先级速查表(从高到低)

优先级 运算符 描述
1 () 小括号(分组)
2 ** 幂运算(右结合)
3 +x -x ~x 一元正、负、按位取反
4 * @ / // % 乘、矩阵乘、除、整除、取模
5 + - 加法、减法
6 << >> 左移、右移
7 & 按位与
8 ^ 按位异或
9 | 按位或
10 in not in is is not < <= > >= != == 成员、身份、比较
11 not 逻辑非
12 and 逻辑与
13 or 逻辑或
14 if–else 条件表达式(三元)
15 lambda Lambda 表达式
16 := 海象表达式(赋值表达式)

记忆口诀:括号最高,幂次一元,乘除加减,移位位运算,比较排后,逻辑垫底,lambda 最后。

同一行优先级相同,按左结合(除 ** 右结合)。不确定时加 () 即可。

time 库基本介绍

time 库包括三类函数

  • 时间获取:time() ctime() gmtime()
  • 时间格式化:strftime() strptime()
  • 程序计时:sleep(), perf_counter()

获取时间

时间格式化

time.strptime(str, tpl)

程序计时

程序计时应用广泛

  • 程序计时指测量起止动作所经历时间的过程
  • 测量时间:perf_counter()
  • 产生时间:sleep()

str(xxx), 将 xxx 转为字符串
int(xxx), 将 xxx 转为 int 数值类型

同时给多个变量赋值:
a, b, c = 1, 3, 5

文本进度条"简单的开始

  • 采用字符串方式打印可以动态变化的文本进度条
  • 进度条需要能在一行中逐渐变化

手动命令行执行 python 文件

  1. 找到安装路径 C:\Users\kk\AppData\Local\Programs\Python\Python35
  2. 控制面板\系统和安全\系统 高级系统设置 Path 变量增加一个值
    image.png
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import time

strWidth = 20
scale = 50
start = time.perf_counter()
print("执行开始".center(strWidth, '-'))
for i in range(scale + 1):
progress = i * 100 / scale
a = '*' * i
b = '.' * (scale - i)
dur = time.perf_counter() - start
print("\r{:^3.0f}%[{}->{}]{:.2f}s".format(progress, a, b, dur), end="")
time.sleep(0.1)
print("\n" + "执行结束".center(strWidth, '-'))
  • 文本进度条程序使用了 perf_counter()计时
  • 计时方法适合各类需要统计时间的计算问题
  • 例如:比较不同算法时间、统计部分程序运行时间

进度条应用

  • 在任何运行时间需要较长的程序中增加进度条
  • 在任何希望提高用户体验的应用中增加进度条
  • 进度条是人机交互的纽带之一

Harrison C. et al. Rethinking the Progress Bar. In ACM Symposium on User Interface Software and Technology, 2007

文本进度条的不同设计函数

结论: 先慢后快的方式更迎合人们

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

strWidth = 20
scale = 50
start = time.perf_counter()
print("执行开始".center(strWidth, '-'))
for i in range(scale + 1):
# 采用 fast power 函数, 增强用户体验
precent = i / scale
newPrecent = (precent + (1 - precent) / 2) ** 8
progress = precent * 100
starCount = int(scale * precent)
a = '*' * starCount
b = '.' * (scale - starCount)
dur = time.perf_counter() - start
print("\r{:^3.0f}%[{}->{}]{:.2f}s".format(progress, a, b, dur), end="")
time.sleep(0.20)
print("\n" + "执行结束".center(strWidth, '-'))