运算符与表达式

15 min中级

算术、比较、逻辑、位运算与运算符优先级。

前置知识

学习目标

  • 掌握「1. 运算符分类 (Operator Categories)」的核心机制、典型用法与常见陷阱
  • 掌握「2. 海象运算符 (Walrus Operator - :=)」的核心机制、典型用法与常见陷阱
  • 掌握「3. 赋值运算符 (Assignment Operators)」的核心机制、典型用法与常见陷阱
  • 掌握「4. 运算符优先级 (Precedence)」的核心机制、典型用法与常见陷阱
  • 掌握「5. 表达式 (Expressions)」的核心机制、典型用法与常见陷阱

1. 运算符分类 (Operator Categories)

1.1 算术运算符 (Arithmetic)

算术运算符用于执行基本的数学运算:

运算符描述示例 (a=10, b=3)
+加法a + b = 13
-减法a - b = 7
*乘法a * b = 30
/除法a / b = 3.333...
//整除(向下取整)a // b = 3
%取模(求余数)a % b = 1
**幂运算a ** b = 1000

1.1.1 算术运算符示例

 # 基本算术运算
 a = 10
 b = 3
 print(f"a + b = {a + b}") # 13
 print(f"a - b = {a - b}") # 7
 print(f"a * b = {a * b}") # 30
 print(f"a / b = {a / b}") # 3.3333333333333335
 print(f"a // b = {a // b}") # 3
 print(f"a % b = {a % b}") # 1
 print(f"a ** b = {a ** b}") # 1000
 # 负数运算
 c = -5
 print(f"-c = {-c}") # 5
 # 浮点数运算
 d = 3.14
 e = 2.71
 print(f"d + e = {d + e}") # 5.85
 print(f"d * e = {d * e}") # 8.5094
 # 混合类型运算
 f = 5
 g = 2.5
 print(f"f + g = {f + g}") # 7.5(结果为浮点数)

讲解:

  1. 速查段总览五个算术运算符:加、减、乘、除、整除。
  2. 注意 Python 的 / 永远返回浮点数。
  3. 详细行为见后文逐项示例。

1.1.2 算术运算符的特殊用法

 # 字符串拼接
 first_name = "Alice"
 last_name = "Smith"
 full_name = first_name + " " + last_name
 print(full_name) # "Alice Smith"
 # 字符串重复
 print("Hello" * 3) # "HelloHelloHello"
 # 列表拼接
 list1 = [1, 2, 3]
 list2 = [4, 5, 6]
 combined = list1 + list2
 print(combined) # [1, 2, 3, 4, 5, 6]
 # 列表重复
 print([0] * 5) # [0, 0, 0, 0, 0]

讲解:

  1. + 对字符串是拼接,对数字是加法——同一符号按类型重载。
  2. 字符串乘整数表示重复:"ab" * 3 得到 "ababab"。
  3. 大量拼接用 join 而不是 +。

1.2 比较运算符 (Relational)

比较运算符用于比较两个值的关系,返回布尔值 “或 False:

运算符描述示例
==等于5 == 5 →“
!=不等于5 != 3 → “
>大于5 > 3 →“
<小于5 < 3 → False
>=大于等于5 >= 5 → “
<=小于等于5 <= 3→False

1.2.1 比较运算符示例

 # 基本比较
 x = 10
 y = 5
 print(f"x == y: {x == y}") # False
 print(f"x != y: {x != y}") #
 print(f"x > y: {x > y}") #
 print(f"x < y: {x < y}") # False
 print(f"x >= y: {x >= y}") #
 print(f"x <= y: {x <= y}") # False
 # 字符串比较(按字典序)
 s1 = "apple"
 s2 = "banana"
 print(f"s1 < s2: {s1 < s2}") # True("apple" 在字典序中小于 "banana")
 # 列表比较(按元素顺序)
 lst1 = [1, 2, 3]
 lst2 = [1, 2, 4]
 print(f"lst1 < lst2: {lst1 < lst2}") # True(第三个元素 3 < 4)
 # 链式比较
 age = 25
 print(f"18 <= age <= 65: {18 <= age <= 65}") #

讲解:

  1. 比较运算返回布尔值 True/False。
  2. 支持链式比较:1 < x < 10 一次写两个条件。
  3. 字符串比较按字典序。

1.3 逻辑运算符 (Logical)

逻辑运算符用于组合多个布尔表达式:

运算符描述短路特性示例
and逻辑与如果左侧为 False,右侧不执行 and False → False
or逻辑或如果左侧为 “,右侧不执行 or False → “
not逻辑非取反布尔值not → False

1.3.1 逻辑运算符示例

 # 基本逻辑运算
 a =
 b = False
 print(f"a and b: {a and b}") # False
 print(f"a or b: {a or b}") #
 print(f"not a: {not a}") # False
 print(f"not b: {not b}") #
 # 短路特性
 # and: 左侧为 False 时,右侧不执行
 def func():
  print("Function executed")
  return
 print(f"False and func(): {False and func()}") # 输出: False(func 未执行)
 print(f" and func(): { and func()}") # 输出: Function executed
  #
 # or: 左侧为  时,右侧不执行
 print(f" or func(): { or func()}") # 输出: True(func 未执行)
 print(f"False or func(): {False or func()}") # 输出: Function executed
  #
 # 实际应用
 age = 20
 is_student =
 if age >= 18 and is_student:
  print("Eligible for student discount")
 # 非布尔值的逻辑运算
 # 0, None, "", [], {}, set() 等被视为 False
 print(f"0 and 5: {0 and 5}") # 0(False)
 print(f"5 and 10: {5 and 10}") # 10(最后一个真值)
 print(f"0 or 5: {0 or 5}") # 5(第一个真值)
 print(f"5 or 10: {5 or 10}") # 5(第一个真值)
 print(f"not 0: {not 0}") #
 print(f"not 'hello': {not 'hello'}") # False

讲解:

  1. and 与 or 返回的不一定是布尔值,而是参与运算的对象。
  2. not 恒返回布尔值。
  3. 短路求值细节见后文。

1.4 位运算符 (Bitwise)

位运算符用于对整数的二进制位进行操作:

运算符描述示例 (a=6 (0110), b=3 (0011))
&按位与a & b = 2 (0010)
``按位或
^按位异或a ^ b = 5 (0101)
~按位取反~a = -7 (补码表示)
<<左移a << 1 = 12 (1100)
>>右移a >> 1 = 3 (0011)

1.4.1 位运算符示例

 # 位运算符示例
 a = 6 # 二进制: 0110
 b = 3 # 二进制: 0011
 print(f"a = {a} (0b{bin(a)[2:]})")
 print(f"b = {b} (0b{bin(b)[2:]})")
 print(f"a & b = {a & b} (0b{bin(a & b)[2:]})") # 2 (0010)
 print(f"a | b = {a | b} (0b{bin(a | b)[2:]})") # 7 (0111)
 print(f"a ^ b = {a ^ b} (0b{bin(a ^ b)[2:]})") # 5 (0101)
 print(f"~a = {~a} (0b{bin(~a)[2:]})") # -7
 print(f"a << 1 = {a << 1} (0b{bin(a << 1)[2:]})") # 12 (1100)
 print(f"a >> 1 = {a >> 1} (0b{bin(a >> 1)[2:]})") # 3 (0011)
 # 应用:检查奇偶数
 num = 7
 if num & 1:
  print(f"{num} 是奇数")
 else:
  print(f"{num} 是偶数")
 # 应用:交换两个数(不使用临时变量)
 x = 10
 y = 20
 print(f"交换前: x={x}, y={y}")
 x ^= y
 y ^= x
 x ^= y
 print(f"交换后: x={x}, y={y}")

讲解:

  1. 位运算直接操作整数的二进制位。
  2. 常用场景:权限位、状态标志位。
  3. 业务代码中较少使用,理解即可。

1.5 成员运算符 (Membership)

成员运算符用于检查一个值是否存在于序列或集合中:

运算符描述示例
in检查值是否在序列中3 in [1, 2, 3] → “
not in检查值是否不在序列中4 not in [1, 2, 3] →“

1.5.1 成员运算符示例

 # 字符串
 text = "Hello, World!"
 print(f"'H' in text: {'H' in text}") #
 print(f"'z' in text: {'z' in text}") # False
 print(f"'World' in text: {'World' in text}") #
 # 列表
 numbers = [1, 2, 3, 4, 5]
 print(f"3 in numbers: {3 in numbers}") #
 print(f"6 in numbers: {6 in numbers}") # False
 # 元组
 coordinates = (10, 20, 30)
 print(f"10 in coordinates: {10 in coordinates}") #
 # 集合
 fruits = {"apple", "banana", "orange"}
 print(f"'apple' in fruits: {'apple' in fruits}") #
 # 字典(检查键)
 person = {"name": "Alice", "age": 30}
 print(f"'name' in person: {'name' in person}") #
 print(f"'Alice' in person: {'Alice' in person}") # False(检查的是键)
 print(f"'Alice' in person.values(): {'Alice' in person.values()}") #

讲解:

  1. 字符串 + 拼接、* 重复。
  2. 与列表类似支持索引与切片。
  3. 字符串不可变:任何“修改”都产生新对象。

1.6 身份运算符 (Identity)

身份运算符用于比较两个对象的内存地址:

运算符描述示例
is检查两个对象是否为同一个对象a is b
is not检查两个对象是否不是同一个对象a is not b
注意: is 与 == 的区别:
  • is 比较的是对象的身份(内存地址)
  • == 比较的是对象的值

1.6.1 身份运算符示例

 # 身份运算符示例
 a = [1, 2, 3]
 b = a # b 指向同一个对象
 c = [1, 2, 3] # c 是一个新对象
 print(f"a is b: {a is b}") # True(指向同一个对象)
 print(f"a == b: {a == b}") # True(值相同)
 print(f"a is c: {a is c}") # False(不同对象)
 print(f"a == c: {a == c}") # True(值相同)
 # 小整数池
 x = 100
 y = 100
 print(f"x is y: {x is y}") # True(小整数被缓存)
 x = 1000
 y = 1000
 print(f"x is y: {x is y}") # False(大整数不被缓存)
 # None 的比较
 value = None
 print(f"value is None: {value is None}") # True(推荐方式)
 print(f"value == None: {value == None}") # True(不推荐)
 # 布尔值
 p =
 q =
 print(f"p is q: {p is q}") # True(布尔值被缓存)

讲解:

  1. is 判断两个变量是否指向同一对象。
  2. 与 == 的区别:is 比身份,== 比值。
  3. 日常只用 x is None。

2. 海象运算符 (Walrus Operator - :=)

Python 3.8 引入的海象运算符允许在表达式内部进行赋值,简化代码结构。

2.1 基本用法

 # 基本用法
 items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
 # 传统方式
 n = len(items)
 if n > 10:
  print(f"Total items: {n}")
 # 使用海象运算符
 if (n := len(items)) > 10:
  print(f"Total items: {n}")
 # 在循环中使用
 while (line := input("Enter a line (or 'quit' to exit): ")) != "quit":
  print(f"You entered: {line}")
 # 在列表推导式中使用
 values = [1, 2, 3, 4, 5]
 squared = [x*x for x in values if (x := x*2) > 5]
 print(squared) # [16, 25](x 先被乘以 2,然后检查是否大于 5)

讲解:

  1. in 判断元素是否在容器中。
  2. 字符串、列表、元组、字典键、集合都支持。
  3. 字典的 in 判断的是键。

2.2 应用场景

 # 读取文件时使用
 with open("example.txt", "r") as f:
  while (line := f.readline()):
  print(line.strip())
 # 正则表达式匹配
 import re
 text = "Contact: john@example.com"
 if match := re.search(r"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})", text):
  print(f"Found email: {match.group(1)}")
 # 复杂条件判断
 user = {"name": "Alice", "age": 30, "active": True}
 if (name := user.get("name")) and (age := user.get("age")) > 18:
  print(f"Welcome, {name}! You are {age} years old.")

讲解:

  1. with open(...) as f 是上下文管理器:离开缩进块自动关闭文件。
  2. 不需要手写 close,异常时也会正确关闭。
  3. 文件读写一律用 with。

3. 赋值运算符 (Assignment Operators)

赋值运算符用于将值赋给变量,包括复合赋值运算符:

运算符描述示例
=简单赋值x = 5
+=加法赋值x += 3 → x = x + 3
-=减法赋值x -= 3 → x = x - 3
*=乘法赋值x *= 3 → x = x * 3
/=除法赋值x /= 3 → x = x / 3
//=整除赋值x //= 3 → x = x // 3
%=取模赋值x %= 3 → x = x % 3
**=幂运算赋值x **= 3 → x = x ** 3
&=按位与赋值x &= 3 → x = x & 3
`=`按位或赋值
^=按位异或赋值x ^= 3 → x = x ^ 3
<<=左移赋值x <<= 1 → x = x << 1
>>=右移赋值x >>= 1 → x = x >> 1

3.1 赋值运算符示例

 # 赋值运算符示例
 x = 10
 print(f"初始 x = {x}")
 x += 5 # x = x + 5
 print(f"x += 5 → x = {x}") # 15
 x -= 3 # x = x - 3
 print(f"x -= 3 → x = {x}") # 12
 x *= 2 # x = x * 2
 print(f"x *= 2 → x = {x}") # 24
 x /= 4 # x = x / 4
 print(f"x /= 4 → x = {x}") # 6.0
 x //= 2 # x = x // 2
 print(f"x //= 2 → x = {x}") # 3.0
 x %= 2 # x = x % 2
 print(f"x %= 2 → x = {x}") # 1.0
 x **= 3 # x = x ** 3
 print(f"x **= 3 → x = {x}") # 1.0
 # 位运算赋值
 y = 6 # 0110
 print(f"初始 y = {y} (0b{bin(y)[2:]})")
 y <<= 1 # y = y << 1
 print(f"y <<= 1 → y = {y} (0b{bin(y)[2:]})") # 12 (1100)
 y >>= 1 # y = y >> 1
 print(f"y >>= 1 → y = {y} (0b{bin(y)[2:]})") # 6 (0110)
 y &= 3 # y = y & 3
 print(f"y &= 3 → y = {y} (0b{bin(y)[2:]})") # 2 (0010)

讲解:

  1. 速查段总览 +=、-=、*= 等复合赋值。
  2. 复合赋值等价于先运算再赋值。
  3. 注意:对列表 += 是原地扩展,= a + b 是新建。

4. 运算符优先级 (Precedence)

运算符优先级决定了表达式中运算的执行顺序,优先级高的运算符先执行:

优先级运算符描述
1()括号(最高优先级)
2**幂运算
3~按位取反
4*, /, //, %乘除、整除、取模
5+, -加减
6<<, >>位移运算
7&按位与
8^按位异或
9``
10==, !=, >, <, >=, <=, is, is not, in, not in比较运算符
11not逻辑非
12and逻辑与
13or逻辑或
14=赋值运算符(最低优先级)

4.1 优先级示例

 # 优先级示例
 # 1. 括号优先
 print((2 + 3) * 4) # 20(先计算括号内的加法)
 # 2. 幂运算优先
 print(2 ** 3 * 4) # 32(先计算 2**3 = 8,再乘以 4)
 print(2 ** (3 * 4)) # 4096(括号改变优先级)
 # 3. 乘除优先于加减
 print(10 + 5 * 2) # 20(先计算 5*2 = 10,再加 10)
 print((10 + 5) * 2) # 30(括号改变优先级)
 # 4. 逻辑运算符优先级
 print( or False and False) # True(and 优先于 or)
 print(( or False) and False) # False(括号改变优先级)
 # 5. 比较运算符与逻辑运算符
 print(5 > 3 and 2 < 4) # True(比较运算符优先于 and)
 print(5 > (3 and 2) < 4) # True(括号改变优先级)

讲解:

  1. Python 运算符有完整优先级表:乘除优先于加减。
  2. 记不住就用括号,括号永远最高。
  3. 复杂表达式拆成多行变量,可读性更好。

5. 表达式 (Expressions)

表达式是由变量、常量、运算符和函数调用组成的代码片段,它会被计算并返回一个值。

5.1 基本表达式

 # 算术表达式
 result = 10 + 5 * 2 # 20
 # 比较表达式
 is_greater = 10 > 5 #
 # 逻辑表达式
 is_valid =  and not False #
 # 成员表达式
 is_present = 3 in [1, 2, 3] #
 # 身份表达式
 is_same = (a is b) # 取决于 a 和 b 是否指向同一对象

讲解:

  1. 纯算术表达式按数学规则求值。
  2. 整型除整型用 / 得浮点数。
  3. 表达式结果类型由操作数决定。

5.2 复杂表达式

 # 复杂表达式
 a = 10
 b = 5
 c = 3
 # 混合运算符
 result = (a + b) * c / 2 # 22.5
 # 条件表达式(三元运算符)
 status = "Adult" if a >= 18 else "Minor"
 # 嵌套表达式
 result = ((a + b) * c) ** 2 # 225
 # 函数调用表达式
 result = len("Hello") + sum([1, 2, 3]) # 5 + 6 = 11

讲解:

  1. 混合运算时按优先级与结合性求值。
  2. 幂运算右结合:2**3**2 是 2**(3**2)。
  3. 可读性优先:多用括号与中间变量。

5.3 表达式求值

Python 表达式的求值遵循运算符优先级和结合性规则:

  • 结合性: 大多数运算符从左到右结合,除了幂运算符(从右到左)
 # 结合性示例
 print(10 - 5 - 3) # 2(从左到右:(10-5)-3)
 print(2 ** 3 ** 2) # 512(从右到左:2**(3**2))
 print(10 / 5 * 2) # 4.0(从左到右:(10/5)*2)

讲解:

  1. 加减乘除左结合:从左到右求值。
  2. 幂运算右结合,赋值右结合。
  3. 结合性只在同级运算符时起作用。

6. 最佳实践

6.1 运算符使用

  • 括号使用: 当表达式复杂时,使用括号提高可读性,即使括号不是必需的
  • 短路特性: 利用 and 和 or 的短路特性优化代码
  • 身份比较: 对于 None、“、False等单例对象,使用is 进行比较
  • 成员检查: 使用 in 运算符检查成员关系,它比手动遍历更高效

6.2 表达式编写

  • 可读性: 保持表达式简洁明了,避免过于复杂的单行表达式
  • 格式化: 对于长表达式,适当换行和缩进以提高可读性
  • 优先级: 了解运算符优先级,避免因优先级问题导致的错误
  • 类型一致性: 确保表达式中的操作数类型兼容

6.3 性能考虑

  • 短路评估: 利用逻辑运算符的短路特性减少不必要的计算
  • 位运算: 在处理位级操作时,位运算符比算术运算符更高效
  • 成员检查: 在大型集合中,in 运算符对 set 和 dict 的检查比 list 和 tuple 更快

算术运算符

基本写法:加法运算 <操作数1> + <操作数2>

# 加法运算
result = 10 + 5

讲解:

  1. + 用于数字相加。
  2. 浮点数相加可能有精度误差。
  3. 字符串/列表相加则是拼接。

基本写法:减法运算 <操作数1> - <操作数2>

# 减法运算
result = 10 - 5

讲解:

  1. - 用于数字相减。
  2. 结果类型:int - int = int,含浮点则为 float。
  3. 减负数等价于加正数。

基本写法:乘法运算 <操作数1> * <操作数2>

# 乘法运算
result = 10 * 5

讲解:

  1. * 用于数字相乘。
  2. 字符串/列表乘整数表示重复。
  3. 大数乘法 Python 自动支持任意精度。

基本写法:除法运算 <操作数1> / <操作数2>

# 除法运算(返回浮点数)
result = 10 / 3

讲解:

  1. / 总是返回浮点数,即使能整除。
  2. 10 / 2 结果是 5.0。
  3. 需要整数结果用 // 或 int()。

基本写法:整除运算 <操作数1> // <操作数2>

# 整除运算(向下取整)
result = 10 // 3

讲解:

  1. // 向下取整:负数时向更小方向。
  2. -7 // 2 得 -4。
  3. 需要向零取整用 int(a / b)。

基本写法:取模运算 <操作数1> % <操作数2>

# 取模运算(求余数)
result = 10 % 3

讲解:

  1. % 返回除法余数。
  2. 结果符号与除数一致(Python 特性)。
  3. 常用于判断奇偶、循环下标。

基本写法:幂运算 <操作数1> ** <操作数2>

# 幂运算
result = 2 ** 3

讲解:

  1. ** 计算幂:2 ** 10 是 1024。
  2. 支持浮点指数:9 ** 0.5 是 3.0。
  3. 大幂运算自动支持,但注意性能。

基本写法:负号运算 -<操作数>

# 负号运算
result = -10

讲解:

  1. 一元负号把数字取反。
  2. 优先级高于乘除。
  3. -2 ** 2 结果是 -4(先算幂)。

基本写法:正号运算 +<操作数>

# 正号运算
result = +10

讲解:

  1. 一元正号不改变数值。
  2. 主要为了代码对称与可读性。
  3. 对字符串等类型不适用。

复合赋值运算符

基本写法:加法赋值 <变量> += <值>

# 加法赋值运算
x = 10
x += 5

讲解:

  1. x += 1 等价于 x = x + 1。
  2. 数字是新建对象再赋值。
  3. 变量必须先存在(有初始值)。

基本写法:减法赋值 <变量> -= <值>

# 减法赋值运算
x = 10
x -= 5

讲解:

  1. x -= 1 等价于 x = x - 1。
  2. 循环计数器中常用。
  3. 复合赋值优先级低于普通运算。

基本写法:乘法赋值 <变量> *= <值>

# 乘法赋值运算
x = 10
x *= 5

讲解:

  1. x *= 2 等价于 x = x * 2。
  2. 对列表:lst *= 2 原地重复内容。
  3. 注意原地与新建的差异。

基本写法:除法赋值 <变量> /= <值>

# 除法赋值运算
x = 10
x /= 5

讲解:

  1. x /= 2 会改变变量类型:int 变 float。
  2. 需要保持整数用 //=.
  3. 复合赋值写法简洁,但类型变化要留意。

基本写法:整除赋值 <变量> //= <值>

# 整除赋值运算
x = 10
x //= 3

讲解:

  1. x //= 2 原地向下取整。
  2. 负数的向下取整方向再复习一遍。
  3. 适合分页等整数运算。

基本写法:取模赋值 <变量> %= <值>

# 取模赋值运算
x = 10
x %= 3

讲解:

  1. x %= n 把 x 限制在 0 到 n-1。
  2. 循环缓冲、环形队列常用。
  3. 结果符号与 n 一致。

基本写法:幂运算赋值 <变量> **= <值>

# 幂运算赋值
x = 2
x **= 3

讲解:

  1. x **= 2 原地平方。
  2. 适合几何增长类计算。
  3. 与其他复合赋值规则一致。

比较运算符

基本写法:等于比较 <操作数1> == <操作数2>

# 等于比较
result = (5 == 5)

讲解:

  1. == 比较值相等。
  2. 不同容器类型比较值而非身份。
  3. 浮点比较用 isclose。

基本写法:不等于比较 <操作数1> != <操作数2>

# 不等于比较
result = (5 != 3)

讲解:

  1. != 是 == 的反操作。
  2. Python 2 的 <> 写法已废弃。
  3. 与 is not 区分:值不等 vs 对象不同。

基本写法:大于比较 <操作数1> > <操作数2>

# 大于比较
result = (5 > 3)

讲解:

  1. > 数值比较大小。
  2. 字符串按字典序比较。
  3. 不同类型比较会报 TypeError。

基本写法:小于比较 <操作数1> < <操作数2>

# 小于比较
result = (5 < 10)

讲解:

  1. < 与 > 对称。
  2. 可用于 datetime、Decimal 等实现了比较协议的对象。
  3. 自定义类实现 lt 即可支持排序。

基本写法:大于等于比较 <操作数1> >= <操作数2>

# 大于等于比较
result = (5 >= 5)

讲解:

  1. >= 含等于。
  2. 排序算法内部大量使用。
  3. 链式写法 a >= b >= c 合法。

基本写法:小于等于比较 <操作数1> <= <操作数2>

# 小于等于比较
result = (5 <= 10)

讲解:

  1. <= 含等于。
  2. 与 >= 对称。
  3. 链式比较从左到右。

链式比较

基本写法:链式比较运算 <值1> < <值2> < <值3>

# 链式比较(等价于 1 < 2 and 2 < 3)
result = 1 < 2 < 3

讲解:

  1. Python 独有语法:1 < x < 3 一次比较。
  2. 中间表达式只求值一次。
  3. 比 and 写法更直观。

逻辑运算符

基本写法:逻辑与运算 <表达式1> and <表达式2>

# 逻辑与运算
result = True and False

讲解:

  1. and 两边都为真才为真。
  2. 返回的是最后一个求值的对象,不一定是 True。
  3. 遇到 False 立即短路。

基本写法:逻辑或运算 <表达式1> or <表达式2>

# 逻辑或运算
result = True or False

讲解:

  1. or 有一边为真即为真。
  2. 返回第一个为真的对象。
  3. 常用作默认值:name = input or "默认"。

基本写法:逻辑非运算 not <表达式>

# 逻辑非运算
result = not True

讲解:

  1. not 取反并返回布尔值。
  2. not 0、not ""、not [] 都是 True(假值取反)。
  3. 别写成 !,Python 没有感叹号逻辑非。

短路求值

基本写法:and 短路返回 <表达式1> and <表达式2>

# and 短路求值,第一个为 False 时返回第一个值
result = False and expensive_operation()

讲解:

  1. False and 任何值 直接返回 False,右侧不求值。
  2. 短路避免无效计算:x != 0 and 10 / x > 1。
  3. 这是安全的条件防护写法。

基本写法:or 短路返回 <表达式1> or <表达式2>

# or 短路求值,第一个为 True 时返回第一个值
result = True or expensive_operation()

讲解:

  1. 真值 or 任何值 直接返回真值,右侧不求值。
  2. 经典用途:默认值 value = user_input or "default"。
  3. 注意空字符串、0 也会触发默认值。

身份运算符

基本写法:is 身份比较 <对象1> is <对象2>

# is 身份比较(判断是否为同一对象)
a = [1, 2, 3]
b = a
result = (a is b)

讲解:

  1. is 比较对象身份(内存地址)。
  2. 小整数驻留可能让 is 结果碰巧为 True,但不要依赖。
  3. 值比较用 ==。

基本写法:is not 身份比较 <对象1> is not <对象2>

# is not 身份比较
a = [1, 2, 3]
b = [1, 2, 3]
result = (a is not b)

讲解:

  1. is not 是 is 的反操作。
  2. 与 != 区分开。
  3. 常用写法 x is not None。

基本写法:使用 is 检查 None <变量> is None

# 使用 is 检查 None
x = None
result = (x is None)

讲解:

  1. x is None 是检查空值的标准写法。
  2. None 是单例对象,is 判断准确且高效。
  3. 不要用 == None。

成员运算符

基本写法:in 成员判断 <元素> in <容器>

# in 成员判断
result = 3 in [1, 2, 3]

讲解:

  1. x in list 判断元素是否存在。
  2. 列表是线性查找,集合/字典是哈希查找更快。
  3. 大列表频繁判断请改用集合。

基本写法:not in 成员判断 <元素> not in <容器>

# not in 成员判断
result = 4 not in [1, 2, 3]

讲解:

  1. not in 是 in 的反操作。
  2. 可读性比 not (x in c) 更好。
  3. 与 is not 一样是组合运算符。

基本写法:字符串成员判断 <子串> in <字符串>

# 字符串子串判断
result = "World" in "Hello, World!"

讲解:

  1. "world" in "hello world" 判断子串。
  2. 大小写敏感。
  3. 需要忽略大小写先 lower()。

基本写法:字典键成员判断 <键> in <字典>

# 字典键成员判断
result = "name" in {"name": "Alice", "age": 30}

讲解:

  1. 字典的 in 判断键是否存在。
  2. 比先 get 再判 None 更语义化。
  3. 高频场景优先用 in 或 setdefault。

位运算符

基本写法:按位与运算 <操作数1> & <操作数2>

# 按位与运算
result = 5 & 3

讲解:

  1. & 对整数二进制位做与。
  2. 常用:flags & MASK 检查某位是否置位。
  3. 注意优先级低于比较运算。

基本写法:按位或运算 <操作数1> | <操作数2>

# 按位或运算
result = 5 | 3

讲解:

  1. | 对二进制位做或。
  2. 常用:组合权限位。
  3. 与逻辑 or 完全不同。

基本写法:按位异或运算 <操作数1> ^ <操作数2>

# 按位异或运算
result = 5 ^ 3

讲解:

  1. ^ 相同位为 0、不同位为 1。
  2. 经典技巧:交换变量、找出现奇数次的数。
  3. 了解即可,业务中少见。

基本写法:按位取反运算 ~<操作数>

# 按位取反运算
result = ~5

讲解:

  1. ~x 等于 -x - 1(补码表示)。
  2. 结果依赖整数位数,容易困惑。
  3. 少用,除非写底层算法。

基本写法:左移运算 <操作数> << <位数>

# 左移运算
result = 5 << 2

讲解:

  1. x << n 等价于 x * 2**n。
  2. 比乘法快,但可读性差。
  3. 适合 2 的幂次运算。

基本写法:右移运算 <操作数> >> <位数>

# 右移运算
result = 20 >> 2

讲解:

  1. x >> n 等价于 x // 2**n(向下取整)。
  2. 负数时与左移对称。
  3. 常用于拆字节。

三元条件运算符

单行写法:三元条件表达式 <值1> if <条件> else <值2>

# 三元条件表达式
age = 20
status = "Adult" if age >= 18 else "Minor"

讲解:

  1. a if 条件 else b:条件为真取 a,否则取 b。
  2. 与 if/else 语句等价,但作为表达式可参与赋值。
  3. 嵌套过多时改用普通 if。

单行写法:嵌套三元表达式 <值1> if <条件1> else (<值2> if <条件2> else <值3>)

# 嵌套三元表达式
score = 85
grade = "A" if score >= 90 else ("B" if score >= 80 else "C")

讲解:

  1. 三元可以嵌套,但可读性急剧下降。
  2. 超过一层就改用 if/elif/else。
  3. 代码是给人读的,简洁优先。

运算符优先级

基本写法:使用括号改变优先级 (<表达式>)

# 使用括号明确运算优先级
result = (2 + 3) * 4

讲解:

  1. 括号强制改变求值顺序。
  2. 即使不必须,加括号也能表达意图。
  3. 团队约定:复杂表达式必须括号化。

海象运算符

基本写法:赋值表达式 (<变量> := <值>)

# 海象运算符(赋值表达式)
if (n := len([1, 2, 3])) > 2:
    print(f"List has {n} elements")

讲解:

  1. := 在表达式中赋值并返回值(Python 3.8+)。
  2. if (n := len(x)) > 5 一次完成赋值+判断。
  3. 减少重复计算,但过度使用伤可读性。

基本写法:在 while 循环中使用海象运算符 while (<变量> := <表达式>): <语句>

# 在 while 循环中使用海象运算符
while (line := input()) != "quit":
    print(line)

讲解:

  1. while (line := f.readline()) != "" 读一行判断一次。
  2. 避免在循环里重复调用 readline。
  3. 经典的文件逐行读取写法。

基本写法:在列表推导式中使用海象运算符 [<变量> for <元素> in <可迭代对象> if (<变量> := <表达式>)]

# 在列表推导式中使用海象运算符
data = [1, 2, 3, 4, 5]
results = [y for x in data if (y := x * 2) > 4]

讲解:

  1. 推导式里用 := 复用计算结果。
  2. [y := f(x) for x in data if y > 0] 计算一次用两次。
  3. 注意作用域:海象变量在推导式外层可见。

表达式求值

基本写法:使用 eval() 求值 eval(<字符串表达式>)

# 使用 eval() 求值字符串表达式
result = eval("2 + 3 * 4")

讲解:

  1. eval("1 + 2") 把字符串当表达式执行。
  2. 危险:注入用户输入可执行任意代码。
  3. 生产代码禁止 eval,改用 ast.literal_eval 或解析器。

运算符重载

换行写法:通过魔术方法重载运算符 class <类名>: def __<运算符方法>__(self, <参数>): <语句>

# 通过 __add__ 方法重载加法运算符
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

讲解:

  1. __add__ 让对象支持 +。
  2. 这是运算符重载机制:符号由特殊方法驱动。
  3. 自定义类实现后 a + b 即调用 a.__add__(b)。

基本写法:重载等于运算符 def __eq__(self, other): <语句>

# 通过 __eq__ 方法重载等于运算符
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

讲解:

  1. __eq__ 让对象支持 ==。
  2. 不实现时默认比较身份。
  3. 重载 eq 通常同时重载 hash 以保持字典行为一致。

基本写法:重载小于运算符 def __lt__(self, other): <语句>

# 通过 __lt__ 方法重载小于运算符
class Student:
    def __init__(self, score):
        self.score = score

    def __lt__(self, other):
        return self.score < other.score

讲解:

  1. __lt__ 支持 <,也是排序的依据。
  2. sorted() 依赖 lt 或 key。
  3. 用 functools.total_ordering 可自动补齐其他比较。

基本写法:重载字符串表示 def __repr__(self): <语句>

# 通过 __repr__ 方法重载字符串表示
class Person:
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return f"Person(name={self.name!r})"

讲解:

  1. __repr__ 定义 repr() 输出,面向开发者。
  2. 调试打印时看到友好信息。
  3. 与 str 的区别:str 面向用户,repr 面向调试。

基本写法:重载长度运算 def __len__(self): <语句>

# 通过 __len__ 方法重载 len() 函数
class Stack:
    def __init__(self):
        self.items = []

    def __len__(self):
        return len(self.items)

讲解:

  1. __len__ 让 len(obj) 可用。
  2. 实现后对象还能用于 bool 判断(长度为 0 为假)。
  3. 容器类自定义大小的标准入口。

基本写法:重载成员判断 def __contains__(self, item): <语句>

# 通过 __contains__ 方法重载 in 运算符
class Matrix:
    def __init__(self, data):
        self.data = data

    def __contains__(self, item):
        return any(item in row for row in self.data)

讲解:

  1. __contains__ 让 x in obj 可用。
  2. 实现后可自定义成员判断逻辑。
  3. 是容器协议的重要组成部分。