Python数据类型
python 数据类型
可变类型与不可变类型的区别
| 可变类型 | 不可变类型 | |
| 数据类型 | list, dict, set, bytearray | int, float, bool, str, tuple, frozenset, bytes |
| 特点 |
1. 修改内容时,对象本身不变,内存地址不变. 2. 不能作为字典的键(因为哈希值会变). |
3. 修改变量的值时,其实是 创建了一个新对象. 4. 可以作为字典的键、集合的元素(因为哈希值不会变) |
可变类型
不可变类型
# ============================
# 1. 列表(list)是可变类型
# ============================
print("=== 列表示例 ===")
lst = [1, 2, 3]
print("初始列表:", lst, "地址:", id(lst))
lst.append(4) # 原地修改
print("append 后:", lst, "地址:", id(lst)) # 地址不变
lst[0] = 99 # 修改元素
print("修改元素后:", lst, "地址:", id(lst)) # 地址仍不变
# ============================
# 2. 字典(dict)是可变类型
# ============================
print("\n=== 字典示例 ===")
d = {"a": 1, "b": 2}
print("初始字典:", d, "地址:", id(d))
d["c"] = 3 # 添加键值对
print("添加键后:", d, "地址:", id(d))
d["a"] = 100 # 修改值
print("修改值后:", d, "地址:", id(d))
# ============================
# 3. 集合(set)是可变类型
# ============================
print("\n=== 集合示例 ===")
s = {1, 2, 3}
print("初始集合:", s, "地址:", id(s))
s.add(4) # 添加元素
print("add 后:", s, "地址:", id(s))
s.remove(2) # 删除元素
print("remove 后:", s, "地址:", id(s))
# ============================
# 4. 可变类型的引用行为
# ============================
print("\n=== 引用行为示例 ===")
a = [1, 2, 3]
b = a # b 指向同一个列表
print("a 地址:", id(a))
print("b 地址:", id(b))
b.append(999)
print("修改 b 后 a:", a) # a 也被修改
print("修改 b 后 b:", b)
# ============================
# 5. 可变类型作为函数参数
# ============================
print("\n=== 函数参数示例 ===")
def modify_list(x):
x.append("new") # 原地修改
lst2 = [10, 20]
print("调用前:", lst2)
modify_list(lst2)
print("调用后:", lst2) # 被修改
# ============================
# 6. 可变类型作为默认参数的陷阱
# ============================
print("\n=== 默认参数陷阱示例 ===")
def add_item(item, container=[]): # 不推荐
container.append(item)
return container
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] 共享了同一个列表!
print(add_item(3)) # [1, 2, 3]
# ============================
# 1. int(整数)是不可变类型
# ============================
print("=== int 示例 ===")
a = 10
print("初始 a:", a, "地址:", id(a))
a = a + 1 # 创建新对象
print("修改后 a:", a, "地址:", id(a)) # 地址变化
# ============================
# 2. float(浮点数)不可变
# ============================
print("\n=== float 示例 ===")
x = 3.14
print("初始 x:", x, "地址:", id(x))
x *= 2 # 创建新对象
print("修改后 x:", x, "地址:", id(x))
# ============================
# 3. bool(布尔)不可变
# ============================
print("\n=== bool 示例 ===")
flag = True
print("flag:", flag, "地址:", id(flag))
flag = not flag # 新对象
print("修改后 flag:", flag, "地址:", id(flag))
# ============================
# 4. str(字符串)不可变
# ============================
print("\n=== str 示例 ===")
s = "hello"
print("初始 s:", s, "地址:", id(s))
s = s + " world" # 拼接会创建新字符串
print("拼接后 s:", s, "地址:", id(s))
# ============================
# 5. tuple(元组)不可变
# ============================
print("\n=== tuple 示例 ===")
t = (1, 2, 3)
print("初始 t:", t, "地址:", id(t))
t = t + (4,) # 拼接生成新元组
print("修改后 t:", t, "地址:", id(t))
# ============================
# 6. frozenset(冻结集合)不可变
# ============================
print("\n=== frozenset 示例 ===")
fs = frozenset([1, 2, 3])
print("初始 fs:", fs, "地址:", id(fs))
fs2 = fs.union([4]) # union 返回新对象
print("union 后 fs2:", fs2, "地址:", id(fs2))
print("原 fs 未变:", fs, "地址:", id(fs))
# ============================
# 7. 不可变类型的引用行为
# ============================
print("\n=== 引用行为示例 ===")
a = 100
b = a # b 指向同一个对象
print("a 地址:", id(a))
print("b 地址:", id(b))
b = b + 1 # b 指向新对象,不影响 a
print("修改后 a:", a, "地址:", id(a))
print("修改后 b:", b, "地址:", id(b))
# ============================
# 8. 不可变类型作为函数参数
# ============================
print("\n=== 函数参数示例 ===")
def modify_value(x):
x = x + 10 # 生成新对象,不影响外部变量
print("函数内部 x:", x, "地址:", id(x))
v = 5
print("调用前 v:", v, "地址:", id(v))
modify_value(v)
print("调用后 v:", v, "地址:", id(v)) # v 不变
python 深拷贝和浅拷贝
| 浅拷贝 | 深拷贝 | |
| 特点 | 创建一个新的外层对象, 内部的子对象(列表、字典等)仍然是共享引用 | 创建一个新的外层对象, 递归复制所有内部子对象, 完全独立 |
| 场景 |
1. 内部对象不会被修改. 2. 数据结构简单(如一维列表). 3. 性能要求高(浅拷贝更快). |
1. 嵌套结构(列表套字典、字典套列表等). 2. 需要完全独立的数据副本. 3. 避免共享引用导致的“连带修改”. |
浅拷贝
深拷贝
import copy
print("=== 基础浅拷贝 ===")
a = [1, 2, [3, 4]]
b = copy.copy(a)
print("a 地址:", id(a))
print("b 地址:", id(b))
print("a[2] 地址:", id(a[2]))
print("b[2] 地址:", id(b[2])) # 内层列表共享
b[2].append(5)
print("修改 b 后 a:", a) # a 被影响
print("修改 b 后 b:", b)
print("\n=== 列表浅拷贝方式 ===")
a = [1, 2, [3, 4]]
b1 = a[:] # 切片
b2 = list(a) # list() 构造
b3 = copy.copy(a) # copy.copy()
for name, b in [("b1", b1), ("b2", b2), ("b3", b3)]:
print(name, "外层地址:", id(b), "内层地址:", id(b[2]))
print("\n=== 字典浅拷贝 ===")
d1 = {"x": 1, "y": [10, 20]}
d2 = d1.copy()
print("d1 地址:", id(d1))
print("d2 地址:", id(d2))
print("d1['y'] 地址:", id(d1["y"]))
print("d2['y'] 地址:", id(d2["y"])) # 内层共享
d2["y"].append(30)
print("修改 d2 后 d1:", d1) # d1 被影响
print("修改 d2 后 d2:", d2)
print("\n=== 集合浅拷贝 ===")
s1 = {1, 2, 3}
s2 = s1.copy()
print("s1 地址:", id(s1))
print("s2 地址:", id(s2))
s2.add(4)
print("修改 s2 后 s1:", s1) # 不影响,因为集合内部没有嵌套
print("修改 s2 后 s2:", s2)
print("\n=== 函数参数中的浅拷贝 ===")
def modify_shallow(lst):
new_lst = lst[:] # 浅拷贝
new_lst[2].append(999) # 修改内层
return new_lst
a = [1, 2, [3, 4]]
result = modify_shallow(a)
print("原列表 a:", a) # 内层被修改
print("返回值 result:", result)
import copy
# 原始数据:包含可变对象
a = [1, [2, 3], {"x": 10}]
# 浅拷贝
b = copy.copy(a)
# 深拷贝
c = copy.deepcopy(a)
# 修改浅拷贝 b
b[1].append(4)
b[2]["x"] = 99
# 修改深拷贝 c
c[1].append(5)
c[2]["x"] = 100
print("a =", a)
print("b =", b)
print("c =", c)
"""
output:
a = [1, [2, 3, 4], {'x': 99}]
b = [1, [2, 3, 4], {'x': 99}]
c = [1, [2, 3, 5], {'x': 100}]
"""