变量装着数据,运算符让数据”流动起来”。上一篇 变量与基本数据类型 我们介绍了 Python 有哪些基本类型,这一篇要把 Python 的七大类运算符一次讲完:算术、比较、赋值、逻辑、位运算、成员运算、身份运算。除此之外,还要讲清楚优先级、短路求值、海象运算符这些初学者很容易忽略但一旦不懂就翻车的细节。
一、算术运算符
Python 的算术运算符除了常规的加减乘除,还有一些特色:
1 | print(7 + 3) # 10 加 |
有两个 需要特别小心的点:
/和//的区别:/总是返回浮点数,即使能整除;//是整除,结果向下取整;- 负数取余:
-7 % 3 = 2,因为 Python 保证(a // b) * b + a % b == a,所以余数与除数同号。这跟 C/Java 不一样,从 C 转来的同学容易踩坑。
字符串和列表也能用部分算术运算符:
1 | print("ab" + "cd") # abcd 拼接 |
二、比较运算符
比较运算符返回 True 或 False:
1 | print(3 < 5) # True |
Python 支持链式比较(很多语言没有),是很 Pythonic 的语法:
1 | age = 25 |
链式比较不仅可读性好,还只求值一次 age,效率更高。
三、赋值运算符
除了普通的 =,Python 还有复合赋值:
1 | x = 10 |
海象运算符 :=(Python 3.8+)
海象运算符可以在表达式中赋值,非常适合”边算边判断”的场景:
1 | # 传统写法 |
再比如读取文件:
1 | # 传统写法 |
海象运算符不是必需的,但合理使用能让代码短一截。
四、逻辑运算符
Python 用英文单词 and、or、not,而不是 &&、||、!:
1 | age = 20 |
短路求值
and 和 or 支持短路:
A and B:A为假则不计算B,直接返回A;A or B:A为真则不计算B,直接返回A。
利用这一点可以写出简洁代码:
1 | # 提供默认值 |
注意:and / or 返回的不一定是 True/False,而是参与运算的操作数本身:
1 | print(3 and 5) # 5 |
需要严格 True/False 时,用 bool(x) 或写 not not x。
五、位运算符
位运算把整数看作二进制串来操作:
1 | a = 0b1100 # 12 |
日常业务代码用不到位运算,但在性能优化、算法竞赛、协议解析、权限位图里非常重要。
一个实用例子——权限系统:
1 | READ = 0b001 # 1 |
六、成员运算符 in / not in
判断元素是否在容器里:
1 | print(3 in [1, 2, 3]) # True |
in 对不同容器复杂度不同:
- list/tuple:O(n),逐个比较;
- set/dict:O(1) 平均,走哈希;
- str:O(n),子串搜索。
所以做大量”是否存在”检查时用 set 或 dict 的 key 更快。
七、身份运算符 is / is not
is 判断两个变量是不是指向同一个对象:
1 | a = [1, 2, 3] |
最常见的正确用法是判断 None:
1 | if result is None: |
None 全局只有一个对象,用 is 判断既高效又语义清晰。不要用 is 判断字符串或数字相等,那会因为 CPython 的缓存优化产生奇怪的结果。
八、运算符优先级
Python 运算符优先级从高到低(简化版):
**幂+x、-x、~x一元*、/、//、%+、-<<、>>&^|- 比较运算符
<,<=,>,>=,!=,==,in,is not xandor:=海象
背这张表没意义——记两件事就够了:
- 不确定时加括号;
not的优先级高于and/or,所以not a == b是not (a == b),不是(not a) == b。
1 | # 别写这种代码: |
九、条件表达式(三元运算符)
Python 有一种紧凑的三元表达式:
1 | # 传统写法 |
顺序和 C 的 ? : 不同,Python 是 “值1 if 条件 else 值2“,读起来更像英语。
嵌套三元虽然可行,但可读性会崩,超过一层建议改回 if:
1 | # 不推荐 |
十、一个综合例子:BMI 计算器
1 | # bmi.py |
这段代码里我们用了:
- 算术运算符
/、**; - 链式比较
0 < weight < 500; - 逻辑运算符
and、not; - 类型转换
float(); - 条件表达式(在
classify_bmi中虽然是 if/elif,但你可以自己改成三元链); - f-string 格式化
:.2f(保留两位小数)。
十一、常见陷阱
- 整数除法陷阱:Python 3 里
10 / 3是3.333...,不是3; - 浮点比较:
0.1 + 0.2 == 0.3是 False,用math.isclose; - and/or 返回值:
3 or 5是3,不是True;需要布尔用bool(); - not 优先级:
not a == b和not (a == b)一样,不要误以为是(not a) == b; - is 判断值:
x is 100有时候巧合是 True,但不可靠,一律用==(或专门判 None); - 链式赋值可变对象:
a = b = []让 a 和 b 都指向同一个空列表,appen 一个 a 都会变; ==与is对字符串:"abc" is "abc"在 CPython 里通常 True(因为字符串驻留),但不要依赖它。
十二、小结与延伸阅读
- 记住
/(浮点除)、//(整除)、%(取余)、**(幂)的区别; - 链式比较
a < b < c是 Python 特有的漂亮写法; and/or短路求值,返回操作数本身而非布尔;- 海象运算符
:=简化”边算边判断”; - 位运算在权限位、性能优化里很有用;
is只用来判断 None 和对象身份;- 遇到复杂表达式记得加括号;
- 条件表达式
A if cond else B是 Python 里的三元运算符。
延伸阅读:
- Python 运算符官方文档:https://docs.python.org/zh-cn/3/reference/expressions.html
- PEP 572 海象运算符:https://peps.python.org/pep-0572/
下一篇 字符串基础与常用方法 我们会深入讲字符串——Python 中用得最多的类型之一。