基础

Python 运算符:算术、整除 // 与取余 %、比较、and/or/not 以及 python round

更新于: · Skillaria.Top

在 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 notnot True → False
同一性is、is notx 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 对值取反。

aba and ba or bnot a
TrueTrueTrueTrueFalse
TrueFalseFalseTrueFalse
FalseTrueFalseTrueTrue
FalseFalseFalseFalseTrue

优先级:先 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.52.7
round(x)四舍五入到最近的整数,恰好一半时取偶数2-23
math.floor(x)向下,趋向负无穷2-32
math.ceil(x)向上,趋向正无穷3-23
math.trunc(x)、int(x)去掉小数部分,趋向零2-22

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 按优先级从高到低执行:

  1. **
  2. 一元运算符 -x、+x、~x
  3. * / // %
  4. + -
  5. 位移与位运算
  6. 比较、in、is
  7. not
  8. and
  9. or
  10. :=

例如 2 + 3 * 4 等于 14,而 (2 + 3) * 4 等于 20。拿不准时就加括号:多余的括号没有任何代价,而优先级错误却很难找到。

运算符的常见错误

错误实际发生的情况正确写法
if x = 5:SyntaxError:这是赋值语句if x == 5:
用 2 ^ 3 求幂按位异或,结果为 12 ** 3
期望 8 / 2 得到整数得到 4.08 // 2
x == 1 or 2总是为真:or 2 恒为真x in (1, 2)
期望 round(2.5) 得到 3银行家舍入结果为 2使用 Decimal 配合 ROUND_HALF_UP
"5" + 5TypeErrorint("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。

通过视频学习本主题

课程“Python 3.15: от новичка до профи”结合实践详细讲解了这一主题。

前往课程