# Day09 · 运算符与表达式 >
Day09 · 运算符与表达式
阶段:阶段一 · 核心基础 | 前置:Day06 | 技术基准:Python 3.15.0
学习目标
- 掌握算术运算符:
+ - * / // % **,以及字符串的+与* - 掌握比较运算符与 Python 特有的链式比较
- 掌握赋值与复合赋值,认识海象运算符
:= - 理解逻辑运算符
and/or/not的短路求值与"返回对象本身"特性 - 认识位运算符
& | ^ ~ << >>、身份运算符is、成员运算符in - 记住运算符优先级,不确定时学会"加括号"
一、算术运算符
| 运算符 | 含义 | 例子 | 结果 |
|---|---|---|---|
+ |
加 / 字符串拼接 | 7 + 2 / "ab"+"cd" |
9 / "abcd" |
- |
减 | 7 - 2 |
5 |
* |
乘 / 字符串重复 | 7 * 2 / "ab" * 3 |
14 / "ababab" |
/ |
真除(得浮点) | 7 / 2 |
3.5 |
// |
整除(向下取整) | 7 // 2 |
3 |
% |
取余 | 7 % 2 |
1 |
** |
幂 | 2 ** 10 |
1024 |
# Author: XiaoJia
a, b = 7, 2
print(a + b) # 9
print(a - b) # 5
print(a * b) # 14
print(a / b) # 3.5 真除
print(a // b) # 3 整除
print(a % b) # 1 取余
print(a ** b) # 49 幂
print(-7 // 2) # -4 向下取整
Day06 已讲过 /、//、% 的区别,这里把它们放进运算符体系整体看一遍。
二、比较运算符与链式比较
| 运算符 | 含义 |
|---|---|
== |
等于 |
!= |
不等于 |
> < |
大于 / 小于 |
>= <= |
大于等于 / 小于等于 |
比较结果都是布尔值 True / False。
x = 15
print(x == 15) # True
print(x != 15) # False
print(x > 10) # True
Python 独有的链式比较:可以像数学里那样连写,不用 and。
x = 15
print(10 < x < 20) # True 等价于 10 < x and x < 20
print(10 < x <= 20) # True
print(1 == 1.0) # True int 与 float 值相等
print("abc" < "abd") # True 字符串按编码逐字符比
字符串比较是逐字符按 Unicode 码点比,不是按长度:
"10" < "9"为True(字符'1'小于'9'),别当成数值比。
三、赋值与复合赋值
3.1、基本赋值
a = 10 # 基本赋值
b = c = 20 # 链式赋值,b、c 都绑到 20
d, e = 1, 2 # 序列解包
d, e = e, d # 一行交换
print(a, b, c, d, e) # 10 20 20 2 1
3.2、复合赋值
+=、-=、*=、/=、//=、%=、**= 等,是"先运算再赋值"的简写。
n = 10
n += 5 # 等价 n = n + 5
print(n) # 15
n *= 2 # n = n * 2
print(n) # 30
n **= 2 # n = n ** 2
print(n) # 900
3.3、海象运算符 :=
Python 3.8+ 引入海象运算符 :=,它能在表达式内部同时赋值并使用变量,省掉一行。
# 传统写法:先赋值再用
line = "Hello"
print(line)
# 海象写法:赋值和使用合一
print((msg := "Hello")) # Hello
print(msg) # Hello msg 已被定义
# 实用场景:边算边判,避免重复调用
import math
if (r := math.sqrt(25)) > 4:
print(f"半径 {r} 大于 4") # 半径 5.0 大于 4
注意:
:=是赋值表达式,外层常需要加括号。它最常见于while读取循环、列表推导里,Day12/Day29 会再遇到。
四、逻辑运算符:and / or / not
| 表达式 | 规则 |
|---|---|
x or y |
x 为假则取 y,否则取 x |
x and y |
x 为假则取 x,否则取 y |
not x |
x 为假则 True,否则 False |
关键特性:and/or 不返回 True/False,而是返回参与运算的对象本身,并且短路求值——左边能定结果就不算右边。
a, b = True, False
print(a and b) # False
print(a or b) # True
print(not a) # False
# 返回对象本身:
print(0 or "hello") # hello 0 为假,取 y
print("hello" and "world") # world hello 为真,取 y
print("" or "默认值") # 默认值 空串为假
# 短路求值:左边为真,or 右边根本不执行
def say():
print("say 被调用了")
return True
False or say() # 会调用 say
True or say() # 不调用 say(短路)
常见套路:用 or 给变量设默认值。
name = ""
display_name = name or "匿名用户"
print(display_name) # 匿名用户
4.1、短路求值为什么重要
短路求值不只是省一次计算,它还能用来防止报错。看下面这个例子:
# 如果 a 是 0,a / b 会触发除零错误;但短路让它根本不会被算到
a, b = 0, 0
print(a != 0 and a / b > 1) # False a!=0 为假,右边不算,不报错
# 如果没有短路,右边 a/b 直接 ZeroDivisionError
or 也同理:open_file() or create_new(),文件打开成功就不创建新的,失败才创建。这种"第一个成功就用第一个"的写法在配置项里很常见:
# 配置优先级:命令行参数 > 环境变量 > 默认值
port = None
env_port = None
final_port = port or env_port or 8080
print(final_port) # 8080 前面两个都为空,落到默认值
五、位运算符
位运算按二进制位操作,高级语言里用得少,但做底层、权限、压缩时会遇到。
| 运算符 | 含义 | 例子 |
|---|---|---|
& |
按位与(同 1 得 1) | 6 & 3 = 2 |
| |
按位或(有 1 得 1) | 6 | 3 = 7 |
^ |
按位异或(不同得 1) | 6 ^ 3 = 5 |
~ |
按位取反 | ~6 = -7 |
<< |
左移(×2) | 6 << 1 = 12 |
>> |
右移(÷2) | 6 >> 1 = 3 |
# 6 = 0b0110,3 = 0b0011
a, b = 6, 3
print(a & b) # 2 0110 & 0011 = 0010
print(a | b) # 7 0110 | 0011 = 0111
print(a ^ b) # 5 0110 ^ 0011 = 0101
print(~a) # -7 取反
print(a << 1) # 12 左移一位 = ×2
print(a >> 1) # 3 右移一位 = ÷2
位运算最经典的三个用途:判断奇偶、快速乘除 2、交换两个变量。
# Author: XiaoJia
# 1. 判断奇偶:偶数最低位是 0,奇数最低位是 1
n = 10
print(n & 1) # 0 偶数
print(11 & 1) # 1 奇数
# 2. 快速乘 2 / 除 2
print(5 << 1) # 10 等价 5*2
print(5 >> 1) # 2 等价 5//2
# 3. 用异或交换两个变量(不借助第三个变量)
x, y = 3, 7
x ^= y
y ^= x
x ^= y
print(x, y) # 7 3 交换完成
对日常业务开发来说,位运算用得不多,知道"能做什么、怎么算"即可。真要用(写底层、权限位、协议解析)时再回来查表。
六、身份运算符 is / is not
is 判断两个名字是否绑定同一个对象(id 相同),is not 取反。Day06 已讲 == vs is,这里归入运算符体系。
x = [1, 2, 3]
y = [1, 2, 3]
z = x
print(x == y) # True 值相等
print(x is y) # False 不同对象
print(x is z) # True 同一个对象
print(x is not y) # True
# 最佳实践:判断空值用 is
data = None
print(data is None) # True
七、成员运算符 in / not in
in 判断某个元素是否在序列(字符串、列表、字典等)中,是 Python 极常用的运算符。
data = [1, 3, 5, 7, 9]
print(5 in data) # True
print(4 in data) # False
print(4 not in data) # True
print("py" in "python") # True 字符串也支持
print("ab" in "abcde") # True
info = {"name": "小嘉", "lang": "Python"}
print("name" in info) # True 字典判断的是 key
print("小嘉" in info) # False 不判断 value
手写循环逐个元素比较是旧时代做法;Python 里一律用
in,简洁且底层优化更好。
八、运算符优先级
表达式里多个运算符同时出现时,按优先级从高到低算,同级从左到右(赋值与幂运算除外)。
| 优先级(高→低) | 运算符 | 说明 |
|---|---|---|
| 1 | () |
括号,最高 |
| 2 | ** |
幂(从右往左) |
| 3 | +x -x ~x |
一元正负、取反 |
| 4 | * / // % |
乘除取模 |
| 5 | + - |
加减 |
| 6 | << >> |
移位 |
| 7 | & |
按位与 |
| 8 | ^ |
按位异或 |
| 9 | | |
按位或 |
| 10 | == != > < >= <= |
比较 |
| 11 | is is not in not in |
身份、成员 |
| 12 | not |
逻辑非 |
| 13 | and |
逻辑与 |
| 14 | or |
逻辑或 |
| 15 | = += -= 等 |
赋值,最低 |
print(2 + 3 * 4) # 14 先乘后加
print((2 + 3) * 4) # 20 括号改变优先级
print(2 ** 3 ** 2) # 512 幂运算从右往左 = 2**(3**2)
print(not True and False) # False not 优先级高于 and
小嘉的实用建议:不要靠背优先级表。拿不准就直接加括号,结果又准、代码又清楚。
8.1、为什么"加括号"是好习惯
优先级表有十几行,没人会逐行背。真实开发里遇到拿不准的表达式,最稳妥的做法不是去查表,而是直接加括号:
# 靠记忆写:你得先想清楚 not 和 and 谁先
# print(not True and False)
# 加括号写:意图一目了然,不必记优先级
print((not True) and False) # False
print(2 + (3 * 4)) # 14
print(2 ** (3 ** 2)) # 512
括号不只是保证结果正确,更是写给下一个读代码的人看的。可读性 > 炫技,这是 Python 之禅里反复强调的。
8.2、表达式 vs 语句
顺带分清两个概念:表达式(Expression)是"有值的一段代码",比如 2 + 3、x > 5、f"你好{name}",它总能算出一个结果;语句(Statement)是"做一件事",比如 if、for、return、赋值 x = 10。运算符把小表达式拼成大表达式,而表达式可以嵌进语句里。今天学的运算符,就是把各种值组装成表达式的"积木"。
8.3、综合小例:算个税的小表达式
把今天学的运算符组装成一个真实表达式——根据月收入算应纳税所得额(简化模型:起征点 5000,税率 10%,速算扣除不考虑)。
# Author: XiaoJia
salary = 12000
threshold = 5000
rate = 0.10
# 应纳税所得额 = 收入 - 起征点(用 max 保证不为负)
taxable = (salary - threshold) if salary > threshold else 0
tax = taxable * rate
print(f"月收入 {salary}")
print(f"应纳税所得额 {taxable}")
print(f"应缴个税 {tax}")
# 复合赋值累加月度税额
total = 0
total += tax
total += tax * 0 # 本月已缴,演示 +=
print(f"累计预缴 {total}")
输出:
月收入 12000
应纳税所得额 7000
应缴个税 700.0
累计预缴 700.0
这个小例子把算术运算、比较、条件判断(Day11 细讲)、复合赋值 +=、f-string 全串起来了。写业务代码时,你就是这样用运算符把一个个小计算拼成完整逻辑的。
8.4、常见误区清单
最后列三条新手最常踩的坑,打个预防针:
- 把
=当数学里的等号:Python 里=是"赋值/绑定",判断相等必须写==。if x = 5是语法错误,要写if x == 5。 - 用
and/or想要布尔值:and/or返回的是对象本身,不是True/False。要布尔结果用bool()或放进if判断。 - 用
is比数值:is比的是内存身份,比数值永远用==(Day06 已强调)。
# 错误示范(注释掉):
# if x = 5: # SyntaxError,应为 ==
# if "hello" is "hello": # 偶尔凑巧为真,但别依赖
九、小结与边界
Day09 把前面几天零散用过的运算符号收编成一张体系表:算术算数值、比较出真假、逻辑做组合、位运算是底层技巧、is/in 是 Python 特色。表达式就是这些运算符搭出来的积木,语句再把表达式包起来做事。
写表达式时牢记两点:拿不准优先级就加括号;and/or 会短路且返回对象本身。明天 Day10 讲输入输出,你就能写出第一个"能跟用户对话"的完整小程序了。
练习题
- 不运行程序,先写出结果再验证:
7 // 2、7 % 2、2 ** 8、-7 // 2。 - 用链式比较判断
score = 75是否在60 ~ 90之间,打印布尔结果。 - 写出
n = 5,然后用复合赋值依次n += 3、n *= 2、n **= 2,说出每步结果。 - 解释
0 or "默认值"、"hello" and "world"、False or 1/0为什么会/不会报错(提示:短路求值)。 - 给定
s = "python",用in判断"th"和"xy"是否是它的子串;再给定列表[10,20,30],判断20是否在内。 - 思考题:
==和is有什么区别?为什么判断x is None比x == None更推荐?
小结
- 算术运算符:
+ - * / // % **;/真除得浮点、//整除向下取整、%取余、**幂。 - 比较运算符返回布尔值;Python 支持链式比较
10 < x < 20,等价于and。 - 赋值:链式
a=b=c、解包a,b=b,a、复合+=等;海象:=在表达式内赋值(3.8+)。 - 逻辑运算
and/or/not:短路求值,且返回对象本身(不是 True/False);常用or设默认值。 - 位运算
& | ^ ~ << >>:按二进制位操作,<<≈×2、>>≈÷2。 - 身份
is比同一对象、成员in判断存在;判空用is None。 - 优先级不必死记,拿不准加括号。

浙公网安备 33010602011771号