运算符与表达式
算术、比较、逻辑、位运算与运算符优先级。
前置知识
- 列表推导式进阶:建议先完成前一篇的学习
学习目标
- 掌握「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(结果为浮点数)
讲解:
- 速查段总览五个算术运算符:加、减、乘、除、整除。
- 注意 Python 的
/永远返回浮点数。 - 详细行为见后文逐项示例。
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]
讲解:
+对字符串是拼接,对数字是加法——同一符号按类型重载。- 字符串乘整数表示重复:
"ab" * 3得到"ababab"。 - 大量拼接用 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}") #
讲解:
- 比较运算返回布尔值 True/False。
- 支持链式比较:
1 < x < 10一次写两个条件。 - 字符串比较按字典序。
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
讲解:
and与or返回的不一定是布尔值,而是参与运算的对象。not恒返回布尔值。- 短路求值细节见后文。
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.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.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(布尔值被缓存)
讲解:
is判断两个变量是否指向同一对象。- 与
==的区别:is 比身份,== 比值。 - 日常只用
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)
讲解:
in判断元素是否在容器中。- 字符串、列表、元组、字典键、集合都支持。
- 字典的 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.")
讲解:
with open(...) as f是上下文管理器:离开缩进块自动关闭文件。- 不需要手写 close,异常时也会正确关闭。
- 文件读写一律用 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)
讲解:
- 速查段总览
+=、-=、*=等复合赋值。 - 复合赋值等价于先运算再赋值。
- 注意:对列表
+=是原地扩展,= a + b是新建。
4. 运算符优先级 (Precedence)
运算符优先级决定了表达式中运算的执行顺序,优先级高的运算符先执行:
| 优先级 | 运算符 | 描述 |
|---|---|---|
| 1 | () | 括号(最高优先级) |
| 2 | ** | 幂运算 |
| 3 | ~ | 按位取反 |
| 4 | *, /, //, % | 乘除、整除、取模 |
| 5 | +, - | 加减 |
| 6 | <<, >> | 位移运算 |
| 7 | & | 按位与 |
| 8 | ^ | 按位异或 |
| 9 | ` | ` |
| 10 | ==, !=, >, <, >=, <=, is, is not, in, not in | 比较运算符 |
| 11 | not | 逻辑非 |
| 12 | and | 逻辑与 |
| 13 | or | 逻辑或 |
| 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(括号改变优先级)
讲解:
- Python 运算符有完整优先级表:乘除优先于加减。
- 记不住就用括号,括号永远最高。
- 复杂表达式拆成多行变量,可读性更好。
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 是否指向同一对象
讲解:
- 纯算术表达式按数学规则求值。
- 整型除整型用
/得浮点数。 - 表达式结果类型由操作数决定。
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
讲解:
- 混合运算时按优先级与结合性求值。
- 幂运算右结合:
2**3**2是 2**(3**2)。 - 可读性优先:多用括号与中间变量。
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)
讲解:
- 加减乘除左结合:从左到右求值。
- 幂运算右结合,赋值右结合。
- 结合性只在同级运算符时起作用。
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>
# 减法运算
result = 10 - 5
讲解:
-用于数字相减。- 结果类型:int - int = int,含浮点则为 float。
- 减负数等价于加正数。
基本写法:乘法运算
<操作数1> * <操作数2>
# 乘法运算
result = 10 * 5
讲解:
*用于数字相乘。- 字符串/列表乘整数表示重复。
- 大数乘法 Python 自动支持任意精度。
基本写法:除法运算
<操作数1> / <操作数2>
# 除法运算(返回浮点数)
result = 10 / 3
讲解:
/总是返回浮点数,即使能整除。10 / 2结果是 5.0。- 需要整数结果用
//或 int()。
基本写法:整除运算
<操作数1> // <操作数2>
# 整除运算(向下取整)
result = 10 // 3
讲解:
//向下取整:负数时向更小方向。-7 // 2得 -4。- 需要向零取整用 int(a / b)。
基本写法:取模运算
<操作数1> % <操作数2>
# 取模运算(求余数)
result = 10 % 3
讲解:
%返回除法余数。- 结果符号与除数一致(Python 特性)。
- 常用于判断奇偶、循环下标。
基本写法:幂运算
<操作数1> ** <操作数2>
# 幂运算
result = 2 ** 3
讲解:
**计算幂:2 ** 10是 1024。- 支持浮点指数:
9 ** 0.5是 3.0。 - 大幂运算自动支持,但注意性能。
基本写法:负号运算
-<操作数>
# 负号运算
result = -10
讲解:
- 一元负号把数字取反。
- 优先级高于乘除。
-2 ** 2结果是 -4(先算幂)。
基本写法:正号运算
+<操作数>
# 正号运算
result = +10
讲解:
- 一元正号不改变数值。
- 主要为了代码对称与可读性。
- 对字符串等类型不适用。
复合赋值运算符
基本写法:加法赋值
<变量> += <值>
# 加法赋值运算
x = 10
x += 5
讲解:
x += 1等价于x = x + 1。- 数字是新建对象再赋值。
- 变量必须先存在(有初始值)。
基本写法:减法赋值
<变量> -= <值>
# 减法赋值运算
x = 10
x -= 5
讲解:
x -= 1等价于x = x - 1。- 循环计数器中常用。
- 复合赋值优先级低于普通运算。
基本写法:乘法赋值
<变量> *= <值>
# 乘法赋值运算
x = 10
x *= 5
讲解:
x *= 2等价于x = x * 2。- 对列表:
lst *= 2原地重复内容。 - 注意原地与新建的差异。
基本写法:除法赋值
<变量> /= <值>
# 除法赋值运算
x = 10
x /= 5
讲解:
x /= 2会改变变量类型:int 变 float。- 需要保持整数用
//=. - 复合赋值写法简洁,但类型变化要留意。
基本写法:整除赋值
<变量> //= <值>
# 整除赋值运算
x = 10
x //= 3
讲解:
x //= 2原地向下取整。- 负数的向下取整方向再复习一遍。
- 适合分页等整数运算。
基本写法:取模赋值
<变量> %= <值>
# 取模赋值运算
x = 10
x %= 3
讲解:
x %= n把 x 限制在 0 到 n-1。- 循环缓冲、环形队列常用。
- 结果符号与 n 一致。
基本写法:幂运算赋值
<变量> **= <值>
# 幂运算赋值
x = 2
x **= 3
讲解:
x **= 2原地平方。- 适合几何增长类计算。
- 与其他复合赋值规则一致。
比较运算符
基本写法:等于比较
<操作数1> == <操作数2>
# 等于比较
result = (5 == 5)
讲解:
==比较值相等。- 不同容器类型比较值而非身份。
- 浮点比较用 isclose。
基本写法:不等于比较
<操作数1> != <操作数2>
# 不等于比较
result = (5 != 3)
讲解:
!=是==的反操作。- Python 2 的
<>写法已废弃。 - 与 is not 区分:值不等 vs 对象不同。
基本写法:大于比较
<操作数1> > <操作数2>
# 大于比较
result = (5 > 3)
讲解:
>数值比较大小。- 字符串按字典序比较。
- 不同类型比较会报 TypeError。
基本写法:小于比较
<操作数1> < <操作数2>
# 小于比较
result = (5 < 10)
讲解:
<与>对称。- 可用于 datetime、Decimal 等实现了比较协议的对象。
- 自定义类实现 lt 即可支持排序。
基本写法:大于等于比较
<操作数1> >= <操作数2>
# 大于等于比较
result = (5 >= 5)
讲解:
>=含等于。- 排序算法内部大量使用。
- 链式写法
a >= b >= c合法。
基本写法:小于等于比较
<操作数1> <= <操作数2>
# 小于等于比较
result = (5 <= 10)
讲解:
<=含等于。- 与 >= 对称。
- 链式比较从左到右。
链式比较
基本写法:链式比较运算
<值1> < <值2> < <值3>
# 链式比较(等价于 1 < 2 and 2 < 3)
result = 1 < 2 < 3
讲解:
- Python 独有语法:
1 < x < 3一次比较。 - 中间表达式只求值一次。
- 比 and 写法更直观。
逻辑运算符
基本写法:逻辑与运算
<表达式1> and <表达式2>
# 逻辑与运算
result = True and False
讲解:
and两边都为真才为真。- 返回的是最后一个求值的对象,不一定是 True。
- 遇到 False 立即短路。
基本写法:逻辑或运算
<表达式1> or <表达式2>
# 逻辑或运算
result = True or False
讲解:
or有一边为真即为真。- 返回第一个为真的对象。
- 常用作默认值:
name = input or "默认"。
基本写法:逻辑非运算
not <表达式>
# 逻辑非运算
result = not True
讲解:
not取反并返回布尔值。not 0、not ""、not []都是 True(假值取反)。- 别写成
!,Python 没有感叹号逻辑非。
短路求值
基本写法:and 短路返回
<表达式1> and <表达式2>
# and 短路求值,第一个为 False 时返回第一个值
result = False and expensive_operation()
讲解:
False and 任何值直接返回 False,右侧不求值。- 短路避免无效计算:
x != 0 and 10 / x > 1。 - 这是安全的条件防护写法。
基本写法:or 短路返回
<表达式1> or <表达式2>
# or 短路求值,第一个为 True 时返回第一个值
result = True or expensive_operation()
讲解:
真值 or 任何值直接返回真值,右侧不求值。- 经典用途:默认值
value = user_input or "default"。 - 注意空字符串、0 也会触发默认值。
身份运算符
基本写法:is 身份比较
<对象1> is <对象2>
# is 身份比较(判断是否为同一对象)
a = [1, 2, 3]
b = a
result = (a is b)
讲解:
is比较对象身份(内存地址)。- 小整数驻留可能让 is 结果碰巧为 True,但不要依赖。
- 值比较用 ==。
基本写法:is not 身份比较
<对象1> is not <对象2>
# is not 身份比较
a = [1, 2, 3]
b = [1, 2, 3]
result = (a is not b)
讲解:
is not是 is 的反操作。- 与
!=区分开。 - 常用写法
x is not None。
基本写法:使用 is 检查 None
<变量> is None
# 使用 is 检查 None
x = None
result = (x is None)
讲解:
x is None是检查空值的标准写法。- None 是单例对象,is 判断准确且高效。
- 不要用
== None。
成员运算符
基本写法:in 成员判断
<元素> in <容器>
# in 成员判断
result = 3 in [1, 2, 3]
讲解:
x in list判断元素是否存在。- 列表是线性查找,集合/字典是哈希查找更快。
- 大列表频繁判断请改用集合。
基本写法:not in 成员判断
<元素> not in <容器>
# not in 成员判断
result = 4 not in [1, 2, 3]
讲解:
not in是 in 的反操作。- 可读性比
not (x in c)更好。 - 与 is not 一样是组合运算符。
基本写法:字符串成员判断
<子串> in <字符串>
# 字符串子串判断
result = "World" in "Hello, World!"
讲解:
"world" in "hello world"判断子串。- 大小写敏感。
- 需要忽略大小写先 lower()。
基本写法:字典键成员判断
<键> in <字典>
# 字典键成员判断
result = "name" in {"name": "Alice", "age": 30}
讲解:
- 字典的 in 判断键是否存在。
- 比先 get 再判 None 更语义化。
- 高频场景优先用 in 或 setdefault。
位运算符
基本写法:按位与运算
<操作数1> & <操作数2>
# 按位与运算
result = 5 & 3
讲解:
&对整数二进制位做与。- 常用:
flags & MASK检查某位是否置位。 - 注意优先级低于比较运算。
基本写法:按位或运算
<操作数1> | <操作数2>
# 按位或运算
result = 5 | 3
讲解:
|对二进制位做或。- 常用:组合权限位。
- 与逻辑 or 完全不同。
基本写法:按位异或运算
<操作数1> ^ <操作数2>
# 按位异或运算
result = 5 ^ 3
讲解:
^相同位为 0、不同位为 1。- 经典技巧:交换变量、找出现奇数次的数。
- 了解即可,业务中少见。
基本写法:按位取反运算
~<操作数>
# 按位取反运算
result = ~5
讲解:
~x等于-x - 1(补码表示)。- 结果依赖整数位数,容易困惑。
- 少用,除非写底层算法。
基本写法:左移运算
<操作数> << <位数>
# 左移运算
result = 5 << 2
讲解:
x << n等价于x * 2**n。- 比乘法快,但可读性差。
- 适合 2 的幂次运算。
基本写法:右移运算
<操作数> >> <位数>
# 右移运算
result = 20 >> 2
讲解:
x >> n等价于x // 2**n(向下取整)。- 负数时与左移对称。
- 常用于拆字节。
三元条件运算符
单行写法:三元条件表达式
<值1> if <条件> else <值2>
# 三元条件表达式
age = 20
status = "Adult" if age >= 18 else "Minor"
讲解:
a if 条件 else b:条件为真取 a,否则取 b。- 与 if/else 语句等价,但作为表达式可参与赋值。
- 嵌套过多时改用普通 if。
单行写法:嵌套三元表达式
<值1> if <条件1> else (<值2> if <条件2> else <值3>)
# 嵌套三元表达式
score = 85
grade = "A" if score >= 90 else ("B" if score >= 80 else "C")
讲解:
- 三元可以嵌套,但可读性急剧下降。
- 超过一层就改用 if/elif/else。
- 代码是给人读的,简洁优先。
运算符优先级
基本写法:使用括号改变优先级
(<表达式>)
# 使用括号明确运算优先级
result = (2 + 3) * 4
讲解:
- 括号强制改变求值顺序。
- 即使不必须,加括号也能表达意图。
- 团队约定:复杂表达式必须括号化。
海象运算符
基本写法:赋值表达式
(<变量> := <值>)
# 海象运算符(赋值表达式)
if (n := len([1, 2, 3])) > 2:
print(f"List has {n} elements")
讲解:
:=在表达式中赋值并返回值(Python 3.8+)。if (n := len(x)) > 5一次完成赋值+判断。- 减少重复计算,但过度使用伤可读性。
基本写法:在 while 循环中使用海象运算符
while (<变量> := <表达式>): <语句>
# 在 while 循环中使用海象运算符
while (line := input()) != "quit":
print(line)
讲解:
while (line := f.readline()) != ""读一行判断一次。- 避免在循环里重复调用 readline。
- 经典的文件逐行读取写法。
基本写法:在列表推导式中使用海象运算符
[<变量> for <元素> in <可迭代对象> if (<变量> := <表达式>)]
# 在列表推导式中使用海象运算符
data = [1, 2, 3, 4, 5]
results = [y for x in data if (y := x * 2) > 4]
讲解:
- 推导式里用 := 复用计算结果。
[y := f(x) for x in data if y > 0]计算一次用两次。- 注意作用域:海象变量在推导式外层可见。
表达式求值
基本写法:使用 eval() 求值
eval(<字符串表达式>)
# 使用 eval() 求值字符串表达式
result = eval("2 + 3 * 4")
讲解:
eval("1 + 2")把字符串当表达式执行。- 危险:注入用户输入可执行任意代码。
- 生产代码禁止 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)
讲解:
__add__让对象支持+。- 这是运算符重载机制:符号由特殊方法驱动。
- 自定义类实现后
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
讲解:
__eq__让对象支持==。- 不实现时默认比较身份。
- 重载 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
讲解:
__lt__支持<,也是排序的依据。- sorted() 依赖 lt 或 key。
- 用 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})"
讲解:
__repr__定义 repr() 输出,面向开发者。- 调试打印时看到友好信息。
- 与 str 的区别:str 面向用户,repr 面向调试。
基本写法:重载长度运算
def __len__(self): <语句>
# 通过 __len__ 方法重载 len() 函数
class Stack:
def __init__(self):
self.items = []
def __len__(self):
return len(self.items)
讲解:
__len__让 len(obj) 可用。- 实现后对象还能用于 bool 判断(长度为 0 为假)。
- 容器类自定义大小的标准入口。
基本写法:重载成员判断
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)
讲解:
__contains__让x in obj可用。- 实现后可自定义成员判断逻辑。
- 是容器协议的重要组成部分。