Python中的浅拷贝与深拷贝

Python中的浅拷贝与深拷贝及其举例分析

在Python编程中,变量的赋值操作默认是进行引用复制,而不是对象复制。因此,当两个变量指向同一个对象时,它们所引用的实际
上是相同的内存地址。这意味着,对其中一个变量进行修改(例如添加、删除或改变元素),都会直接影响到另一个变量,因为它们
共享同一对象。

浅拷贝

浅拷贝仅复制变量表中的指针,使得两个新变量引用原对象的内存地址。这种操作非常快,适用于大多数简单数据类型,如整数、字
符串和小型的列表或元组。以下是一个浅拷贝的示例:

a = [1, 2, 3]
b = a
print(id(a), id(b))  # 输出相同的内存地址

在这个例子中,ba 引用的是同一个列表对象。因此,当你对 a 进行修改时,如添加一个元素:

a.append(4)
print(a)        # [1, 2, 3, 4]
print(b)        # [1, 2, 3, 4]

可以看到,b 也反映了这个修改。

深拷贝

深拷贝则是对每个对象进行复制,确保新变量和原对象的引用都是独立的。这意味着,对于复杂数据结构(如嵌套列表、元组或自定
义类),深拷贝可以避免外部变量的修改影响到内部变量。以下是进行深拷贝的示例:

import copy

a = [1, 2, 3]
b = copy.deepcopy(a)
print(id(a), id(b))  # 输出不同的内存地址

在这个情况下,b 引用的对象与 a 独立,因此,当对 a 进行修改时,b 保持不变:

a.append(4)
print(a)        # [1, 2, 3, 4]
print(b)        # [1, 2, 3]
举例说明

示例一:浅拷贝与深拷贝对不同数据类型的影响

# 浅拷贝
a = [1, 2, 3]
b = a
print("a ID:", id(a), "b ID:", id(b))  # 输出相同的内存地址

# 深拷贝
import copy
c = copy.deepcopy(a)
print("a ID:", id(a), "c ID:", id(c))  # 输出不同的内存地址

# 修改原对象,观察浅拷贝和深拷贝的结果
a.append(4)
print("a:", a)
print("b (浅拷贝):", b)  # 结果会显示添加后的元素
print("c (深拷贝):", c)  # 结果保持不变

示例二:对象属性的浅拷贝与深拷贝

假设我们有一个类 Point,包含一个属性 xy

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

a = Point(1, 2)
b = a  # 浅拷贝
c = copy.deepcopy(a)  # 深拷贝

print("a:", a.x, a.y)
print("b (浅拷贝):", b.x, b.y)  # 结果相同,因为 b 和 a 是同一对象
print("c (深拷贝):", c.x, c.y)  # 结果相同,但因为 deepcopy 创建了新对象

# 修改原对象的属性,观察两者的变化
a.x = 3
print("修改后的 a:", a.x, a.y)
print("b (浅拷贝):", b.x, b.y)  # 展示了对浅拷贝变量的影响
print("c (深拷贝):", c.x, c.y)  # 保持不变,因为 deepcopy 创建了独立的对象

示例三:列表中的嵌套结构(深拷贝的必要性)

import copy

my_list = [
    [1, 2],        # 子列表
    {'name': 'Alice', 'age': 30},  # 字典
    ('string', 5),   # 元组
    Point(4, 5)     # 自定义类实例
]

# 浅拷贝
shallow_copy = my_list.copy()
print(shallow_copy is my_list)  # False,因为列表的 copy 方法是浅拷贝

# 深拷贝
deep_copy = copy.deepcopy(my_list)
print(deep_copy is my_list)    # False,独立的对象

# 修改原始对象中的某个元素
my_list[0][0] = 11
print("修改后的原对象:", my_list)

# 浅拷贝后的结果
print("浅拷贝后:", shallow_copy)

# 深拷贝后的结果
print("深拷贝后:", deep_copy)

示例四:字符串的拷贝(无需深拷贝)

s = "Hello, Python!"
t = s

print(t is s)  # True,因为字符串是不可变对象,t引用了同一内存地址
# 修改 t 时会影响 s,但因为字符串是 immutable(不可变),这样其实不会有任何变化。

t += " world"  # 这里实际上是重新创建了一个新的字符串对象,而不是修改原有的。

print(s)        # 'Hello, Python!'
print(t)       # 'Hello, Python! world'

总结

通过以上例子可以看出,浅拷贝和深拷贝在不同情况下有不同的效果。浅拷贝适用于大多数简单数据类型,而对复杂的嵌套结构或自定义类对象,则必须使用深拷贝,以确保每个变量都有独立的对象副本,从而避免外部修改影响到内部变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值