# 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、常见误区清单

最后列三条新手最常踩的坑,打个预防针:

  1. 把 = 当数学里的等号:Python 里 = 是"赋值/绑定",判断相等必须写 ==。if x = 5 是语法错误,要写 if x == 5。
  2. 用 and/or 想要布尔值:and/or 返回的是对象本身,不是 True/False。要布尔结果用 bool() 或放进 if 判断。
  3. 用 is 比数值:is 比的是内存身份,比数值永远用 ==(Day06 已强调)。
# 错误示范(注释掉):
# if x = 5:        # SyntaxError,应为 ==
# if "hello" is "hello":   # 偶尔凑巧为真,但别依赖

九、小结与边界

Day09 把前面几天零散用过的运算符号收编成一张体系表:算术算数值、比较出真假、逻辑做组合、位运算是底层技巧、is/in 是 Python 特色。表达式就是这些运算符搭出来的积木,语句再把表达式包起来做事。

写表达式时牢记两点:拿不准优先级就加括号;and/or 会短路且返回对象本身。明天 Day10 讲输入输出,你就能写出第一个"能跟用户对话"的完整小程序了。

练习题

  1. 不运行程序,先写出结果再验证:7 // 2、7 % 2、2 ** 8、-7 // 2。
  2. 用链式比较判断 score = 75 是否在 60 ~ 90 之间,打印布尔结果。
  3. 写出 n = 5,然后用复合赋值依次 n += 3、n *= 2、n **= 2,说出每步结果。
  4. 解释 0 or "默认值"、"hello" and "world"、False or 1/0 为什么会/不会报错(提示:短路求值)。
  5. 给定 s = "python",用 in 判断 "th" 和 "xy" 是否是它的子串;再给定列表 [10,20,30],判断 20 是否在内。
  6. 思考题:== 和 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。
  • 优先级不必死记,拿不准加括号。

扩展阅读

posted @ 2026-11-01 19:44  小嘉游戏  阅读(10)  评论(0)    收藏  举报