python笔记:赋值,浅拷贝和深拷贝

在 Python 中,变量赋值、浅拷贝和深拷贝在处理对象时有不同的行为和应用场景。以下是它们的详细区别:

1. 赋值

赋值操作只是创建了一个新的引用(别名)来指向同一个对象。也就是说,赋值操作并不创建新的对象,原始对象和赋值后的变量指向同一块内存区域。

a = [1, 2, 3]
b = a  # b 是 a 的引用
b[0] = 99

print("a:", a)  # 输出: [99, 2, 3]
print("b:", b)  # 输出: [99, 2, 3]

如上所示,修改 b 的内容也会影响到 a,因为它们指向同一个对象。

2. 浅拷贝

浅拷贝创建了一个新的对象,但并不递归地复制子对象。新的对象包含了对原始对象中子对象的引用,因此修改新对象的子对象也会影响到原始对象。

import copy

a = [1, 2, [3, 4]]
b = copy.copy(a)  # 创建 a 的浅拷贝
b[2][0] = 99

print("a:", a)  # 输出: [1, 2, [99, 4]]
print("b:", b)  # 输出: [1, 2, [99, 4]]

如上所示,修改 b 的子对象也会影响到 a,因为浅拷贝只是复制了对子对象的引用。

3. 深拷贝

深拷贝创建了一个新的对象,并且递归地复制所有的子对象。新对象和原始对象完全独立,修改新对象不会影响到原始对象。

import copy

a = [1, 2, [3, 4]]
b = copy.deepcopy(a)  # 创建 a 的深拷贝
b[2][0] = 99

print("a:", a)  # 输出: [1, 2, [3, 4]]
print("b:", b)  # 输出: [1, 2, [99, 4]]

如上所示,修改 b 的子对象不会影响到 a,因为深拷贝创建了完全独立的对象。

总结

  • 赋值:创建一个新的引用,原始对象和新变量指向同一个对象。
  • 浅拷贝:创建一个新的对象,但只复制了对象的顶层,子对象仍然是原始对象的引用。
  • 深拷贝:创建一个新的对象,并递归地复制所有子对象,新对象和原始对象完全独立。

在讨论赋值、浅拷贝和深拷贝时,了解“顶层”、“层级”和“子对象”的概念很重要。这些术语有助于理解对象的结构以及不同复制方法的影响。

顶层、层级、子对象的概念

  1. 顶层 (Top-level):

    • 顶层是指对象的第一个层级,也就是对象本身。比如,一个列表对象的顶层就是这个列表本身,而不是它包含的元素。
  2. 层级 (Level):

    • 层级表示对象的嵌套深度。例如,一个列表中包含另一个列表,那么第一个列表是第一个层级,第二个列表是第二个层级。
  3. 子对象 (Sub-object):

    • 子对象是指包含在另一个对象中的对象。例如,一个列表中的元素(如果这些元素也是对象)就是这个列表的子对象。

示例说明

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

在上面的例子中:

  • 顶层对象是 nested_list 这个列表。
  • 第一层级包含元素 1, 2, 和 [3, 4]
  • 元素 [3, 4] 是第二层级,它是一个子对象。

赋值、浅拷贝、深拷贝的影响

  1. 赋值:

    • 赋值不会创建新对象,两个变量指向同一个对象。
    • 修改任何层级的对象,都会影响所有引用。
    a = [1, 2, [3, 4]]
    b = a  # 赋值,a 和 b 指向同一个对象
    b[2][0] = 99  # 修改子对象
    print(a)  # 输出: [1, 2, [99, 4]]
    print(b)  # 输出: [1, 2, [99, 4]]
    
  2. 浅拷贝:

    • 浅拷贝创建一个新的顶层对象,但子对象仍然是引用原来的对象。
    • 修改顶层对象不影响原对象,但修改子对象会影响原对象。
    import copy
    
    a = [1, 2, [3, 4]]
    b = copy.copy(a)  # 浅拷贝
    b[0] = 99  # 修改顶层对象
    print(a)  # 输出: [1, 2, [3, 4]]
    print(b)  # 输出: [99, 2, [3, 4]]
    
    b[2][0] = 99  # 修改子对象
    print(a)  # 输出: [1, 2, [99, 4]]
    print(b)  # 输出: [99, 2, [99, 4]]
    
  3. 深拷贝:

    • 深拷贝创建一个新的顶层对象,并递归地复制所有子对象,生成一个完全独立的对象。
    • 修改任何层级的对象都不会影响原对象。
    import copy
    
    a = [1, 2, [3, 4]]
    b = copy.deepcopy(a)  # 深拷贝
    b[0] = 99  # 修改顶层对象
    print(a)  # 输出: [1, 2, [3, 4]]
    print(b)  # 输出: [99, 2, [3, 4]]
    
    b[2][0] = 99  # 修改子对象
    print(a)  # 输出: [1, 2, [3, 4]]
    print(b)  # 输出: [99, 2, [99, 4]]
    

何时使用

  • 赋值: 当你不需要独立的副本,只需要多个引用来操作同一个对象时。
  • 浅拷贝: 当你需要一个顶层对象的副本,但允许子对象共享时。
  • 深拷贝: 当你需要一个完全独立的对象,包括所有层级的子对象都不共享时。

理解这些概念和它们的影响有助于选择适当的复制方法,以满足特定的编程需求。

posted @ 2024-07-18 11:30  清澈的澈  阅读(7)  评论(0编辑  收藏  举报