Python 运算符:算术、整除 // 与取余 %、比较、and/or/not 以及 python round
在 Python 中,/ 总是得到 float,// 向下取整得到整数部分,% 是余数,** 是幂。round(x, n) 按「银行家舍入」保留 n 位小数:round(2.5) 得到 2,round(3.5) 得到 4;向上和向下取整分别使用 math.ceil 和 math.floor,绝对值则由 abs 给出。
Python 运算符是把值变成新值的符号:+ 做加法,// 做整除,and 把条件连接起来。下面给出完整的运算符列表和示例,说明 / 与 // 的区别、and、or、not 的逻辑,以及取整函数:python round、math.ceil、math.floor 和 abs。所有示例都可以粘贴到 REPL 中验证。
Python 运算符列表
运算符按用途分组。不必整张表都背下来:实际代码中最常见的是算术、比较和逻辑连接。
| 分组 | 运算符 | 示例 |
|---|---|---|
| 算术 | + - * / // % ** | 7 // 2 → 3 |
| 比较 | == != < > <= >= | 3 < 5 → True |
| 逻辑 | and or not | not True → False |
| 同一性 | is、is not | x is None |
| 成员 | in、not in | "咖" in "咖啡" → True |
| 赋值 | = += -= *= /= //= %= **= | total += 250 |
| 海象运算符 | := | if (n := len(s)) > 10: |
| 位运算 | & | ^ ~ << >> | 5 & 3 → 1 |
算术运算符
加、减、乘的用法和数学课上一样。只要表达式中有一个 float,结果也是 float:2 + 1.0 得到 3.0。Python 的整数不会溢出:2 ** 100 会被精确计算,无论有多少位数字。
>>> 250 + 120
370
>>> 12.5 * 3
37.5
>>> 2 ** 10
1024
>>> 2 ** 0.5
1.4142135623730951
Python 中的幂运算:** 运算符
乘方使用两个星号,而不是 ^:在 Python 中 ^ 表示按位异或,因此 2 ^ 3 得到的是 1,而不是 8。分数指数可以求根:9 ** 0.5 得到 3.0。还有函数 pow(x, y),效果相同;它的第三个参数用于取模:pow(2, 10, 1000) 得到 24。
注意优先级:** 的优先级高于一元负号,所以 -2 ** 2 等于 -4。如果想求负数的平方,请加括号:(-2) ** 2。
Python 中的除法:/、// 和 %
Python 有两种除法,这是新手最常遇到的意外来源。普通除法 / 总是返回 float,即使能整除也一样。整除 // 去掉小数部分,而 % 返回余数。
>>> 7 / 2
3.5
>>> 8 / 2
4.0
>>> 7 // 2
3
>>> 7 % 2
1
整除 // 与取余 %:实际应用
// 和 % 组合起来可以解决「整数部分是多少、还剩多少」的问题。课程中的开销记录器把金额存为分,以免丢失精度,然后把总额拆分为元和分:
kopecks = 125050 # 以分为单位存储金额
rub = kopecks // 100 # 1250 — 整数部分(元)
kop = kopecks % 100 # 50 — 余数(分)
print(rub, kop) # 1250 50
print(40 // 7, "周零", 40 % 7, "天") # 5 周零 5 天
内置函数 divmod 一次返回两个结果:divmod(125050, 100) 得到元组 (1250, 50)。余数也可以用来判断奇偶:n % 2 == 0 对偶数为真。
负数:// 向下取整
运算符 // 不只是去掉小数,而是向下取整,即趋向负无穷。对正数没有区别,对负数则不同。Python 中余数 % 的符号与除数相同,因此总有 a == (a // b) * b + a % b 成立。
>>> -7 // 2
-4
>>> -7 % 2
1
>>> int(-7 / 2) # 去掉小数部分,而不是向下取整
-3
除以零:会出现什么错误
用三种运算符中的任何一种除以零,都会抛出 ZeroDivisionError 异常。整数和小数都一样。可以用 try/except 捕获,也可以事先检查除数。
>>> 10 / 0
Traceback (most recent call last):
...
ZeroDivisionError: division by zero
>>> count = 0
>>> avg = 1500 / count if count else 0
>>> avg
0
比较运算符
比较运算的结果是 True 或 False。判断相等使用两个等号 ==,单个 = 是赋值。字符串按字符编码逐个比较,所以 "Z" < "a" 为真:大写字母排在小写字母之前。
>>> 250 == 250.0
True
>>> 3 != 4
True
>>> 1 < 5 <= 10 # 链式比较:1 < 5 and 5 <= 10
True
>>> 0.1 + 0.2 == 0.3
False
像 0 <= x < 100 这样的链式比较是 Python 的一个便利特性,不需要写 and。最后一行提醒你小数的误差:0.1 + 0.2 的结果是 0.30000000000000004。比较小数时请使用 math.isclose(a, b),金额则应存为分或使用 Decimal。
逻辑运算符 and、or、not
Python 的逻辑运算符是英文单词,而不是其他语言中的 && 和 ||。and 在两边都为真时为真,or 在至少一边为真时为真,not 对值取反。
| a | b | a and b | a or b | not a |
|---|---|---|---|---|
| True | True | True | True | False |
| True | False | False | True | False |
| False | True | False | True | True |
| False | False | False | False | True |
优先级:先 not,然后 and,最后 or。表达式 True or False and False 的结果是 True,因为 and 先计算。复杂条件中请加括号,这样你和同事都更容易读懂。
and 与 or 实际返回什么
and 和 or 返回的不一定是 True 或 False,而是其中的一个操作数。or 返回第一个为真的值(如果都不为真,则返回最后一个),and 返回第一个为假的值(如果都为真,则返回最后一个)。被视为假的值有:0、0.0、空字符串、空集合、None 和 False。
>>> name = ""
>>> name or "访客"
'访客'
>>> 5 and 0
0
>>> not ""
True
求值是惰性的:如果左边已经决定了结果,右边就不会被计算。因此当 count == 0 时,count and total / count 不会因除以零而出错。与另外两个不同,not 总是返回 bool。
is 与 in 运算符
== 比较的是值,而 is 检查两个名字是否指向同一个对象。两个内容相同的空购物篮相等,但它们不是同一个对象。is 最常用的场景是判断 None:if x is None。
>>> a = [250, 120]
>>> b = [250, 120]
>>> a == b, a is b
(True, False)
>>> c = a
>>> c is a
True
不要用 is 比较数字或字符串:有时它「碰巧」能用,是因为解释器对对象做了缓存,但结果依赖具体实现;对于 x is 5 这样的写法,Python 还会发出 SyntaxWarning。
运算符 in 检查成员关系:字符串中的子串、列表中的元素、字典中的键。not in 则相反。
>>> "咖啡" in "咖啡和点心"
True
>>> "餐饮" in {"餐饮": 450, "打车": 300}
True
>>> 5 not in [1, 2, 3]
True
赋值运算符与海象运算符 :=
复合赋值 +=、-=、*=、//= 等是简写:total += 250 等同于 total = total + 250。Python 没有 ++ 和 -- 运算符:写 x++ 会导致语法错误。
海象运算符 :=(因为它看起来像海象的眼睛和獠牙而得名)可以在表达式内部完成赋值。当你既需要检查一个值,又需要在之后使用它时,它很有用:
items = ["咖啡", "打车", "午饭", "电影"]
if (n := len(items)) > 3:
print(f"支出条目太多:{n}")
while (line := input("金额:")) != "":
print(int(line) * 2)
没有海象运算符的话,就得调用两次 len,或者把赋值单独写成一行。不要滥用它:如果一行代码变得难以阅读,普通赋值更好。
Python 中的取整:round、ceil、floor
Python 的取整工具包括内置函数 round 以及 math 模块中的函数。它们解决的是不同问题,混淆它们是常见错误。
| 函数 | 作用 | 2.5 | -2.5 | 2.7 |
|---|---|---|---|---|
round(x) | 四舍五入到最近的整数,恰好一半时取偶数 | 2 | -2 | 3 |
math.floor(x) | 向下,趋向负无穷 | 2 | -3 | 2 |
math.ceil(x) | 向上,趋向正无穷 | 3 | -2 | 3 |
math.trunc(x)、int(x) | 去掉小数部分,趋向零 | 2 | -2 | 2 |
Python 的 round 函数与银行家舍入
函数 round(x, n) 保留 n 位小数;如果省略第二个参数,则返回整数 int。最容易踩的坑是:python round 采用「银行家舍入」,即恰好一半时舍入到最近的偶数。因此 round(2.5) 得到 2,而 round(3.5) 得到 4。这样在大量计算中,舍入误差不会总朝同一个方向累积。
>>> round(2.5), round(3.5)
(2, 4)
>>> round(3.14159, 2)
3.14
>>> round(1250, -2) # 精确到百位
1200
>>> round(2.675, 2) # 不是 2.68:二进制下它是 2.67499...
2.67
如果需要中学里习惯的「五入」,例如在收据中,请使用 Decimal 配合 ROUND_HALF_UP 模式。数字要以字符串形式传入,以免继承 float 的误差:
>>> from decimal import Decimal, ROUND_HALF_UP
>>> Decimal("2.5").quantize(Decimal("1"), ROUND_HALF_UP)
Decimal('3')
>>> Decimal("2.675").quantize(Decimal("0.01"), ROUND_HALF_UP)
Decimal('2.68')
课程中还有一条规则:只在输出时取整。要美观地打印,不需要 round,用 f 字符串就够了:f"{amount:.2f}" 显示两位小数,而数值本身保持精确。
math.ceil 与 math.floor:向上和向下取整
当「不够」是不可接受的时候,就用 math.ceil:例如要订几辆大巴、需要多少页才能放下所有结果。math.floor 则用于只计算完整单位的场景。两个函数都返回 int。
import math
guests = 47
seats = 20
print(math.ceil(guests / seats)) # 3 辆大巴
print(math.floor(9.99)) # 9
print(-(-guests // seats)) # 3 — 不用 math 实现 ceil,靠 // 的技巧
模块 math 中还有其他有用的函数:math.sqrt(平方根)、math.isclose(比较小数)、math.pi、math.gcd。Python 3.15 新增了子模块 math.integer(PEP 791),用于整数运算:其中有 comb、factorial、gcd、isqrt、lcm、perm,而旧的 math.gcd 等仍然可用。
abs 函数:数的绝对值
abs(x) 返回绝对值,即去掉符号后与零的距离。这是内置函数,无需导入。它适用于整数、小数,甚至复数:对于 3+4j,它返回向量的长度 5.0。
>>> abs(-250)
250
>>> abs(-12.5)
12.5
>>> budget, spent = 5000, 5320
>>> abs(budget - spent) # 偏差了多少
320
典型用法是忽略方向的差值,以及带容差的比较:abs(a - b) < 0.001。对于小数,math.isclose 更可靠,因为它会考虑数值的量级。
运算符优先级
一个表达式中有多个运算符时,Python 按优先级从高到低执行:
**- 一元运算符
-x、+x、~x * / // %+ -- 位移与位运算
- 比较、
in、is notandor:=
例如 2 + 3 * 4 等于 14,而 (2 + 3) * 4 等于 20。拿不准时就加括号:多余的括号没有任何代价,而优先级错误却很难找到。
运算符的常见错误
| 错误 | 实际发生的情况 | 正确写法 |
|---|---|---|
if x = 5: | SyntaxError:这是赋值语句 | if x == 5: |
用 2 ^ 3 求幂 | 按位异或,结果为 1 | 2 ** 3 |
期望 8 / 2 得到整数 | 得到 4.0 | 8 // 2 |
x == 1 or 2 | 总是为真:or 2 恒为真 | x in (1, 2) |
期望 round(2.5) 得到 3 | 银行家舍入结果为 2 | 使用 Decimal 配合 ROUND_HALF_UP |
"5" + 5 | TypeError | int("5") + 5 |
总结
记住最关键的几点:/ 总是得到 float,// 向下取整,% 返回与除数同号的余数,乘方用 **。逻辑运算符 and、or、not 用英文单词书写并惰性求值,is 用于判断 None。Python 的 round 按偶数舍入,向上和向下取整分别用 math.ceil 和 math.floor,绝对值由 abs 给出。本课程会在实践中讲解这些运算符,例如用分来存储金额的开销记录器。
常见问题
如何在 Python 中保留两位小数?
使用 round(x, 2);如果只是想美观地输出,用 f 字符串 f"{x:.2f}",它不会改变数值本身。
为什么 Python 中 round(0.5) 得到 0?
因为 round 在恰好一半时舍入到最近的偶数,而 0 是偶数;同理 round(1.5) 和 round(2.5) 都得到 2。
如何在 Python 中得到除法的整数部分?
使用 //:17 // 5 得到 3。对负数它向下取整,所以 -17 // 5 得到 -4;如果想让结果向零截断,请使用 int(-17 / 5)。
Python 有三元运算符吗?
有,它是条件表达式:值1 if 条件 else 值2,例如 "偶数" if n % 2 == 0 else "奇数"。
Python 中 & 和 and 有什么区别?
and 是逻辑运算符,带惰性求值;& 是整数的按位与,也是集合的交集。在 if 条件中请使用 and。