在Python学习与面试中,变量相关的概念确实有不少容易混淆或出错的地方。以下我整理了常考点和易错点,并附上示例说明。
一、常考点
1. 变量赋值与内存地址(id、is)
- •
== 比较值是否相等,is 比较内存地址是否相同。
a = [1, 2, 3]
b = a # b和a指向同一对象
c = [1, 2, 3] # c是新对象
print(a is b) # True
print(a is c) # False
print(a == c) # True
2. 可变与不可变对象
- • 不可变:
int, float, str, tuple, frozenset。修改会创建新对象。 - • 可变:
list, dict, set。原地修改不会创建新对象。
x = 10
y = x
x += 1# 不可变 → 新对象
print(y) # 10
lst1 = [1, 2]
lst2 = lst1
lst1.append(3) # 可变 → 影响 lst2
print(lst2) # [1, 2, 3]
3. 全局变量与 global / nonlocal
- • 嵌套函数修改外层函数变量需
nonlocal。
x = 100
deffunc():
global x
x = 200# 修改全局x
defouter():
y = 1
definner():
nonlocal y
y = 2
4. 变量类型动态性
Python 变量没有类型,对象才有。同一变量可先后指向不同类型。
var = 10# int
var = "hello"# str
二、易错点
1. 默认参数的陷阱
函数默认参数在定义时计算并保存,不是每次调用时重新创建。因此可变默认参数会累积修改。
defadd_item(item, lst=[]):
lst.append(item)
return lst
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] ← 错误预期:[2]
# 正确做法
defadd_item(item, lst=None):
if lst isNone:
lst = []
lst.append(item)
return lst
2. 链式赋值与可变对象
a = b = []
a.append(1)
print(b) # [1] → a和b是同一对象
a = b = []
a = [1]
print(b) # [] → a被重新赋值,不影响b
3. 对不可变对象“修改”的误解
t = (1, 2, [3, 4])
t[2].append(5) # 可以,因为元组内列表可变
# t[0] = 0 # 报错,元组本身不可变
4. 变量作用域规则(LEGB)
函数内赋值默认创建局部变量,会“遮蔽”外部同名变量。
x = 10
deffunc():
print(x) # 想用全局x,但下面有x=...
x = 20# 导致上一行报错(UnboundLocalError)
解决:在函数首行声明 global x。
5. 删除变量与引用计数
a = [1, 2, 3]
b = a
del a # 删除变量a,不删除对象
print(b) # [1, 2, 3] 仍然存在
6. 循环中变量遗留问题
列表推导式中的变量在 Python 3 中不会泄漏到外部,但普通 for 循环会。
for i inrange(5):
pass
print(i) # 4,i仍然存在
# 推导式
[i for i inrange(5)]
print(i) # 仍然是4,不会覆盖外部i(Python 3)
7. 整数缓存机制(小整数池)
Python 会缓存 -5 到 256 的整数,导致 is 出现意外结果。
a = 256
b = 256
print(a is b) # True(缓存)
c = 257
d = 257
print(c is d) # False(未缓存,取决于实现)
建议:比较整数用 == 而非 is。
8. 切片赋值与浅拷贝
a = [1, 2, [3, 4]]
b = a[:] # 浅拷贝,内层列表仍是同一个
a[2].append(5)
print(b[2]) # [3, 4, 5] → 被影响
# 深拷贝需要 import copy; copy.deepcopy()
三、总结记忆口诀