12.1 变量是什么? #
在 Python 中,变量是贴在对象上的标签,不是装数据的盒子。赋值是把标签指向某个对象:
a = 10
a = "hello" # 标签改指向新对象,不是把 10 改成字符串变量本身没有固定类型,类型属于它当前指向的对象。
12.2 命名规则 #
| 规则 | 说明 |
|---|---|
| 字符 | 字母、数字、下划线 |
| 开头 | 不能以数字开头 |
| 关键字 | 不能用 if、class 等保留字 |
项目里遵循 PEP 8:变量用 snake_case,见名知意。
user_name = "Alice" # 推荐
max_retry_count = 3
# userName = "Alice" # 变量不推荐驼峰(类名才用)12.3 常用赋值 #
# 元组解包
name, age = "Bob", 25
# 交换变量
x, y = 10, 20
x, y = y, x12.3.1 链式赋值的陷阱 #
可变对象(列表、字典)用 a = b = [] 会共享同一个对象,改一个会影响另一个:
a = b = []
a.append(1)
print(b) # [1] —— b 也被改了
# 正确:分别创建
a, b = [], []12.4 is 与 == #
| 运算符 | 比较的是 |
|---|---|
== |
值是否相等 |
is |
是否是同一个对象(同一内存) |
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True,内容相同
print(a is b) # False,两个列表对象
print(a is c) # True,同一对象
value = None
if value is None: # 判断 None 用 is
print("value 是 None")12.5 可变对象 vs 不可变对象 #
| 类型 | 分类 | 修改时 |
|---|---|---|
int、float、str、tuple |
不可变 | 生成新对象 |
list、dict、set |
可变 | 原地修改,id 不变 |
# 不可变:赋值产生新对象
s = "hi"
s += "!" # 新字符串
print(s) # hi!
# 可变:原地修改
lst = [1, 2, 3]
lst.append(4) # 仍是同一个列表对象
print(lst) # [1, 2, 3, 4]
lst2 = lst
lst.append(5)
print(lst2) # [1, 2, 3, 4, 5] —— 共享引用,一并变化12.6 浅拷贝和深拷贝 #
import copy
list1 = [1, 2, [3, 4]]
shallow_copy = copy.copy(list1)
print('原始list1:', list1)
print('浅拷贝shallow_copy:', shallow_copy)
# 修改嵌套元素
list1[2][0] = 99
print('修改list1[2][0]为99后')
print('list1:', list1)
print('shallow_copy:', shallow_copy) # 嵌套部分也会变化
list2 = [1, 2, [3, 4]]
deep_copy = copy.deepcopy(list2)
print('原始list2:', list2)
print('深拷贝deep_copy:', deep_copy)
# 修改嵌套元素
list2[2][0] = 88
print('修改list2[2][0]为88后')
print('list2:', list2)
print('deep_copy:', deep_copy) # 不会变化12.7 函数中的常见陷阱 #
12.7.1 传递可变对象 #
函数收到的是对象引用;在函数内修改列表/字典会影响外部,重新赋值则不会:
def add_item(items):
"""
向传入的列表中添加一个元素99。
注意:此操作会修改原列表。
"""
items.append(99) # 外部列表会变
def reset(items):
"""
清空传入的列表。
注意:此操作会修改原列表,使其为空列表。
"""
items.clear() # 外部列表会被清空
my_list = [1, 2, 3]
print("原列表:", my_list)
add_item(my_list)
print("添加99后:", my_list)
reset(my_list)
print("重置后:", my_list)12.7.2 可变默认参数(高频 bug) #
# 错误:默认列表只创建一次,多次调用会累积
def add(x, lst=[]):
lst.append(x)
return lst
print(add(1)) # 输出: [1]
print(add(2)) # 输出: [1, 2] 这是一个错误
# 正确
def add_fixed(x, lst=None):
if lst is None:
lst = []
lst.append(x)
return lst
print(add_fixed(1)) # 输出: [1]
print(add_fixed(2)) # 输出: [2]12.8 项目开发要点 #
- 变量是引用:赋值、传参传递的是对象引用,不是拷贝(除非显式
copy) - 判断空值用
is None:不要用== None - 比较内容用
==:不要用is比较字符串、列表的值(is只用于None、同一对象) - 共享列表要小心:配置、缓存等传给多处时,明确是共享还是
.copy()副本 - 默认参数不要用
[]或{}:用None再在函数内创建 - 嵌套数据要深拷贝:
copy.deepcopy(),浅拷贝只复制最外层