2.3. 数学运算¶
Python 开箱即用就可以当作计算器使用。本页介绍你最常用到的运算符:数值上的算术运算、产生布尔值的比较运算、组合条件的逻辑运算符,以及用于硬件层面工作的位运算符。
2.3.1. 算术运算¶
+—— 加法-—— 减法(或作为前缀表示取负:-x)*—— 乘法/—— 除法。始终 返回一个float,即使两个操作数都是整数。//—— 向下取整除法。返回向负无穷方向取整的整数商。%—— 取模(求余数)。**—— 幂运算(2 ** 10等于 1024)。
>>> 7 / 2
3.5
>>> 7 // 2
3
>>> -7 // 2
-4
>>> 7 % 2
1
>>> 2 ** 16
65536
混合类型的算术运算会自动将整数提升为浮点数:
>>> 3 + 0.5
3.5
增强赋值将运算符与 = 结合起来,以紧凑的方式进行就地更新:
counter = 0
counter += 1 # equivalent to counter = counter + 1
counter *= 2 # works for *= /= //= %= **= too
运算符优先级遵循常规顺序:先 **,然后是一元 -,接着是 *、/、// 和 %,最后是 + 和 -。不确定时就用括号——它们在运行时不会带来任何开销。
2.3.2. 比较运算¶
比较运算符返回一个 bool(True 或 False):
==和!=—— 等于 / 不等于。<、<=、>、>=—— 排序比较。
>>> 3 == 3
True
>>> 3 == 3.0
True
>>> 3 < 5 <= 5
True
最后一个示例是一个 链式 比较,它完全等价于 3 < 5 and 5 <= 5。
警告
= 用于赋值;== 用于比较。表达式 if x = 5: 之所以是语法错误,正是因为 Python 拒绝悄无声息地混淆这两者。
2.3.3. 布尔逻辑¶
有三个运算符可以组合布尔值:
and—— 只有两边都为真时才为True。or—— 任意一边为真时即为True。not—— 对单个布尔值取反。
and 和 or 会 短路:一旦结果已经确定,它们就停止求值。False and slow_check() 永远不会调用 slow_check。
and 和 or 还会返回它们其中一个操作数,而不是字面的 True 或 False,这让你能够紧凑地编写默认值:
name = user_name or "anonymous" # "" / 0 / None are falsy
2.3.4. 位运算符¶
对于硬件工作——打包寄存器字段、屏蔽位、解析协议头——你会用到位运算符。它们作用于 int 的二进制表示:
&—— 按位与|—— 按位或^—— 按位异或~—— 按位取反(一的补码)<<—— 左移>>—— 右移
在读写这些内容时,十六进制和二进制字面量形式非常方便:
>>> 0b1100 & 0b1010
8 # 0b1000
>>> 0b1100 | 0b1010
14 # 0b1110
>>> 0xFF ^ 0x0F
240 # 0xF0
>>> 1 << 8
256
>>> (0xABCD >> 8) & 0xFF
171 # extract the high byte
每个位运算符都有对应的增强形式:|=、&=、^=、<<=、>>=。
备注
and / or 作用于布尔值(或真值性);& / | 作用于位。不要把它们弄混。0b1100 and 0b1010 的结果是 0b1010,因为两个操作数都为真值——这通常不是你在操作位时想要的结果。
2.3.5. 实用的数值内置函数¶
有少数几个内置函数涵盖了运算符本身无法完成的常见数值操作:
round()—— 取最近的整数,或在给定第二个参数时取最近的ndigits位小数。round(x)返回int,round(x, n)返回float。遇到正中间的情况(0.5、1.5……)会取最近的偶数,而不总是向上取整。divmod()—— 在一次调用中返回(quotient, remainder)。在把一个量拆分为多个单位时很方便(把秒拆成分和秒,把字节拆成页和偏移量)。pow()—— 两参数形式与**相同。三参数形式pow(base, exp, mod)在计算(base ** exp) % mod时不会真正生成那个庞大的中间值,这是对大指数进行模幂运算的唯一实用方法。
>>> round(3.7)
4
>>> round(3.14159, 2)
3.14
>>> round(0.5) # ties go to even, not always up
0
>>> round(1.5)
2
>>> divmod(125, 60) # 125 seconds = 2 min, 5 sec
(2, 5)
>>> minutes, seconds = divmod(125, 60)
>>> pow(3, 4) # same as 3 ** 4
81
>>> pow(3, 100, 7) # (3 ** 100) mod 7, efficient
4
整数到字符串的进制转换(bin、oct、hex)在 字符串方法与格式化 中介绍。
2.3.6. math 模块¶
常见的数学函数位于 math 模块中。导入它一次,然后通过点号名称调用其函数:
import math
print(math.sqrt(2)) # 1.4142135
print(math.sin(math.pi / 2)) # 1.0
print(math.floor(3.7)) # 3
print(math.log(100, 10)) # 2.0
MicroPython 的 math 模块涵盖了常见的函数(sqrt、exp、log、sin、cos、tan、atan2、floor、ceil、pi、e ……)。需要随机数时,请参阅 random 模块;对于定点位运算,上面的运算符通常就足够了。
2.3.7. 复数¶
对于需要虚部的数值工作,Python 提供了 complex 类型,并带有 j 后缀的字面量(1 + 2j)。cmath 模块对复数输入的支持与 math 相对应。两者在大多数 MicroPython 构建中都存在,但在摄像头工作中很少需要;这里主要是提一下它们,以免你在移植使用了它们的代码时感到意外。