卡码笔记-最强八股文
首页
计算机基础
Python
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
大模型Github (opens new window)
代码随想录 (opens new window)
首页
计算机基础
Python
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
大模型Github (opens new window)
代码随想录 (opens new window)
  • 本栏必读

    • Python面试题专栏介绍
    • Python学习路线
    • Python零基础入门课
  • 基础语法

  • 函数、作用域与模块

  • 面向对象

  • 进阶语法与语言机制

    • 可迭代对象和迭代器有什么区别?
    • 生成器是什么?yield为什么能节省内存?
    • Python装饰器的原理是什么?
    • Python上下文管理器是什么?with如何自动释放资源?
    • Python异常体系是什么?try、except、else和finally怎么执行?
    • Python浅拷贝和深拷贝有什么区别?
      • 简要回答
      • 详细回答
      • 知识拓展
    • Python类型标注有什么用?常见类型应该怎么写?
    • dataclass、namedtuple和普通类有什么区别?
    • Python如何管理内存?引用计数和垃圾回收是什么?

# Python浅拷贝和深拷贝有什么区别?

面试官问:"Python中浅拷贝和深拷贝有什么区别?"

很多人会答"浅拷贝拷贝一层,深拷贝拷贝所有层",但这个说法不够准确。真正要讲清楚的是:浅拷贝创建新容器但共享内部元素对象,深拷贝递归创建所有层级的新对象;修改浅拷贝的嵌套结构会影响原对象,深拷贝完全独立。

# 简要回答

浅拷贝(Shallow Copy) 创建一个新的容器对象,但容器内的元素仍然是原对象中元素的引用。外层容器是新的,内部元素是共享的。

深拷贝(Deep Copy) 递归创建新对象,包括容器和容器内的所有嵌套对象。原对象和拷贝对象完全独立,修改任何一方都不影响另一方。

核心区别:

  • 浅拷贝:新容器,共享元素。修改嵌套可变对象会互相影响。
  • 深拷贝:所有对象都是新的。完全独立,互不影响。

常见浅拷贝方式:切片list[:]、工厂函数list()、dict.copy()、copy.copy()。

深拷贝方式:只有copy.deepcopy()。

# 详细回答

# 赋值 vs 浅拷贝 vs 深拷贝

先理解三者的区别:

import copy

original = [[1, 2], [3, 4]]

# 赋值: 不创建新对象,只是新名字指向同一对象
assigned = original

# 浅拷贝: 创建新列表,但内部列表是共享的
shallow = copy.copy(original)
# 或: shallow = original[:]
# 或: shallow = list(original)

# 深拷贝: 递归创建所有层级的新对象
deep = copy.deepcopy(original)

print(original is assigned)      # True
print(original is shallow)       # False
print(original[0] is shallow[0]) # True (内部列表共享)
print(original is deep)          # False
print(original[0] is deep[0])    # False (内部列表也是新的)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 浅拷贝的行为

修改浅拷贝的嵌套对象会影响原对象:

import copy

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

# 修改外层列表: 不影响原对象
shallow.append([5, 6])
print(original)  # [[1, 2], [3, 4]]
print(shallow)   # [[1, 2], [3, 4], [5, 6]]

# 修改内层列表: 影响原对象
shallow[0].append(99)
print(original)  # [[1, 2, 99], [3, 4]]
print(shallow)   # [[1, 2, 99], [3, 4], [5, 6]]
1
2
3
4
5
6
7
8
9
10
11
12
13
14

因为original[0]和shallow[0]指向同一个列表对象,修改这个列表会在两边都可见。

# 深拷贝的行为

修改深拷贝的任何层级都不影响原对象:

import copy

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

# 修改外层
deep.append([5, 6])
print(original)  # [[1, 2], [3, 4]]

# 修改内层
deep[0].append(99)
print(original)  # [[1, 2], [3, 4]] 不受影响
print(deep)      # [[1, 2, 99], [3, 4], [5, 6]]
1
2
3
4
5
6
7
8
9
10
11
12
13

original[0]和deep[0]是两个独立的列表对象。

浅拷贝与深拷贝的对象关系

# 常见浅拷贝方式

列表的浅拷贝:

original = [1, [2, 3]]

shallow1 = original[:]          # 切片
shallow2 = list(original)       # 工厂函数
shallow3 = original.copy()      # copy方法
shallow4 = copy.copy(original)  # copy模块

# 都是浅拷贝
print(shallow1[1] is original[1])  # True
1
2
3
4
5
6
7
8
9

字典的浅拷贝:

original = {"a": [1, 2]}

shallow1 = original.copy()      # copy方法
shallow2 = dict(original)       # 工厂函数
shallow3 = copy.copy(original)  # copy模块

# 都是浅拷贝
print(shallow1["a"] is original["a"])  # True
1
2
3
4
5
6
7
8

集合的浅拷贝:

original = {1, 2, 3}
shallow = original.copy()
1
2

# 不可变对象的拷贝

对于不可变对象(整数、字符串、元组),浅拷贝和深拷贝都可能返回原对象:

import copy

num = 42
num_copy = copy.copy(num)
print(num is num_copy)  # True (不可变对象,不需要拷贝)

text = "hello"
text_copy = copy.deepcopy(text)
print(text is text_copy)  # True

# 但嵌套可变对象的元组会被深拷贝
original = ([1, 2], [3, 4])
deep = copy.deepcopy(original)
print(original is deep)        # False
print(original[0] is deep[0])  # False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

这是优化:不可变对象拷贝后也无法修改,共享引用不会有副作用。

# 处理循环引用

深拷贝可以处理循环引用:

import copy

original = [1, 2]
original.append(original)  # 循环引用自己

deep = copy.deepcopy(original)
print(deep[2] is deep)  # True (保持了循环引用结构)
print(deep[2] is original)  # False (是新对象)
1
2
3
4
5
6
7
8

deepcopy会跟踪已经拷贝的对象,避免无限递归。

# 自定义拷贝行为

类可以定义__copy__()和__deepcopy__()控制拷贝行为:

import copy

class MyClass:
    def __init__(self, value):
        self.value = value
    
    def __copy__(self):
        print("执行浅拷贝")
        return MyClass(self.value)
    
    def __deepcopy__(self, memo):
        print("执行深拷贝")
        return MyClass(copy.deepcopy(self.value, memo))

obj = MyClass([1, 2])
shallow = copy.copy(obj)      # 执行浅拷贝
deep = copy.deepcopy(obj)     # 执行深拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

memo字典用于跟踪已拷贝的对象,处理循环引用。

# 知识拓展

Q1: 什么时候用浅拷贝,什么时候用深拷贝?

  • 浅拷贝:内部元素是不可变对象(数字、字符串),或者确实想共享内部对象。性能更好,内存占用更小。
  • 深拷贝:需要完全独立的副本,修改拷贝不能影响原对象。嵌套结构包含可变对象(列表、字典)时通常需要深拷贝。

Q2: 为什么字典的.copy()是浅拷贝?

字典的copy()方法只拷贝字典本身,不递归拷贝值对象。这是性能和常见需求的平衡:大多数时候只需要拷贝一层,深拷贝开销大且不总是必需。

Q3: 函数参数传递是拷贝吗?

不是。Python函数参数是对象引用传递,不是拷贝。传入列表时,函数内外的变量指向同一个列表对象:

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

data = [1, 2, 3]
modify(data)
print(data)  # [1, 2, 3, 4]
1
2
3
4
5
6

如果需要避免修改原对象,应该在函数内手动拷贝:

def modify(lst):
    lst = lst.copy()  # 浅拷贝
    lst.append(4)
    return lst
1
2
3
4

可以查看Python函数参数是值传递还是引用传递?了解参数传递机制。

Q4: 切片[:]一定是浅拷贝吗?

对于内置容器(列表、元组、字符串),切片创建新对象,但内部元素是共享的,属于浅拷贝:

original = [[1, 2], [3, 4]]
sliced = original[:]
print(original is sliced)        # False
print(original[0] is sliced[0])  # True
1
2
3
4

Q5: 如何拷贝自定义对象?

如果自定义类没有定义__copy__和__deepcopy__,copy模块会:

  • 浅拷贝:创建新实例,__dict__浅拷贝。
  • 深拷贝:创建新实例,__dict__深拷贝。

通常这个默认行为就够用。需要特殊逻辑(如不拷贝某些属性)时才需要自定义。

Last Updated: 10/13/2026, 5:57:00 PM

← Python异常体系是什么?try、except、else和finally怎么执行? Python类型标注有什么用?常见类型应该怎么写? →

评论

验证登录状态...

侧边栏 侧边栏
夜间模式 夜间
卡码简历 卡码简历
代码随想录 代码随想录
卡码投递表 卡码投递表🔥
2026实习校招群 2026群
添加客服微信 2026实习校招客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记 支持卡码笔记
鼓励/支持/赞赏Carl 卡码笔记赞赏码
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪