python赋值、传参、浅拷贝与深拷贝详解

在Python中,理解变量赋值、参数传递以及拷贝操作的区别非常重要,这关系到你对数据可变性和内存管理的理解。

基本概念

直接赋值 (=)

直接赋值是将一个对象的引用赋给另一个变量,两个变量指向同一个内存地址。

函数参数传递

Python中的参数传递是"按对象引用传递"(pass by object reference)。对于可变对象,函数内修改会影响原始对象;对于不可变对象,则不会影响。

浅拷贝 (Shallow Copy)

浅拷贝创建一个新对象,但只复制原对象的第一层内容。对于嵌套的可变对象,仍然共享引用。

  • 创建一个新对象,但新对象中的元素是对原对象中元素的引用
  • 只拷贝对象本身,不拷贝对象内部的子对象
  • 对于可变对象(如列表、字典),修改浅拷贝对象中的可变元素会影响原对象

深拷贝 (Deep Copy)

深拷贝创建一个新对象,并递归地复制所有嵌套对象,完全独立于原始对象。

  • 创建一个新对象,并且递归地拷贝原对象中的所有元素
  • 完全独立于原对象,修改新对象不会影响原对象
  • 对于嵌套结构,会创建所有嵌套对象的副本

操作实例

直接赋值

a = [1, 2, 3]
b = a  # 直接赋值

b.append(4)
print(a)  # 输出: [1, 2, 3, 4] - a也被修改了
print(a is b)  # 输出: True - 是同一个对象

函数参数传递

def modify_list(lst):
    lst.append(4)

my_list = [1, 2, 3]
modify_list(my_list)
print(my_list)  # 输出: [1, 2, 3, 4] - 原始列表被修改

def modify_number(num):
    num += 1

x = 5
modify_number(x)
print(x)  # 输出: 5 - 原始数值未被修改

浅拷贝的实现方法

  • 使用切片操作 [:]
  • 使用 list()dict() 等构造函数
  • 使用 copy() 方法
  • 使用 copy.copy() 函数
import copy

# 方法1: 使用copy模块的copy()函数
new_list = copy.copy(original_list)

# 方法2: 对于列表可以使用切片
new_list = original_list[:]

# 方法3: 使用list()构造函数
new_list = list(original_list)

# 方法4: 对于字典可以使用dict()构造函数或copy()方法
new_dict = dict(original_dict)
new_dict = original_dict.copy()

深拷贝的实现方法

import copy

new_list = copy.deepcopy(original_list)
new_dict = copy.deepcopy(original_dict)

示例对比

操作创建新对象独立于原始对象嵌套对象处理
直接赋值共享
浅拷贝部分独立共享
深拷贝完全独立独立

列表的浅拷贝 vs 深拷贝

import copy

original = [1, 2, [3, 4]]
shallow = copy.copy(original)
deep = copy.deepcopy(original)

# 修改原始列表的第一个元素
original[0] = 10
print(original)  # [10, 2, [3, 4]]
print(shallow)   # [1, 2, [3, 4]] - 第一层不受影响
print(deep)      # [1, 2, [3, 4]] - 完全不受影响

# 修改原始列表的内部列表
original[2][0] = 30
print(original)  # [10, 2, [30, 4]]
print(shallow)   # [1, 2, [30, 4]] - 内部列表被修改
print(deep)      # [1, 2, [3, 4]]  - 仍然不受影响

字典的浅拷贝 vs 深拷贝

import copy

original = {'a': 1, 'b': [2, 3]}
shallow = copy.copy(original)
deep = copy.deepcopy(original)

# 修改原始字典的值
original['a'] = 10
print(original['a'])  # 10
print(shallow['a'])   # 1 - 不受影响
print(deep['a'])      # 1 - 不受影响

# 修改原始字典的内部列表
original['b'][0] = 20
print(original['b'])  # [20, 3]
print(shallow['b'])   # [20, 3] - 被修改
print(deep['b'])      # [2, 3]  - 不受影响

何时使用浅拷贝或深拷贝

使用浅拷贝的情况

  • 对象没有嵌套结构或所有元素都是不可变的(如数字、字符串、元组)
  • 你希望新对象与原对象共享内部的可变对象
  • 性能考虑(深拷贝更耗资源)

使用深拷贝的情况

  • 对象包含嵌套的可变结构
  • 你需要完全独立的副本,不希望修改影响原对象
  • 不确定对象结构但需要确保完全独立

注意事项

  1. 对于不可变对象(如数字、字符串、元组),浅拷贝和深拷贝没有区别,因为它们不能被修改
  2. 深拷贝可以处理递归对象(对象包含对自己的引用)
  3. 自定义类可以通过实现__copy__()__deepcopy__()方法来控制拷贝行为

理解浅拷贝和深拷贝的区别对于避免意外的副作用和bug非常重要,特别是在处理复杂的数据结构时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

callinglove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值