MST

星途 面试题库

面试题:Python深拷贝与浅拷贝在复杂对象结构下的内存行为

有一个自定义类 `MyClass`,类中有一个列表属性 `data`。创建一个 `MyClass` 的实例 `obj1` 并初始化 `data` 为 `[1, [2, 3]]`。然后对 `obj1` 进行浅拷贝得到 `obj2`,对 `obj1` 进行深拷贝得到 `obj3`。如果现在修改 `obj1.data[1][0]` 为4,分析 `obj1`、`obj2`、`obj3` 内存中的变化以及它们各自 `data` 属性的内存占用情况。
43.8万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试
  1. 内存变化分析
    • obj1
      • 由于直接修改了 obj1.data[1][0] 为 4,obj1.data 列表的引用不变,但是 obj1.data[1] 这个子列表中索引为 0 的元素发生了改变,即内存中对应位置的值从 2 变为 4。
    • obj2
      • 因为 obj2obj1 的浅拷贝,obj2.dataobj1.data 是不同的列表对象(引用不同),但是 obj2.data 中的子列表 obj2.data[1]obj1.data[1] 是同一个对象(引用相同)。所以当 obj1.data[1][0] 被修改为 4 时,obj2.data[1][0] 也会变为 4 ,因为它们指向内存中的同一个子列表对象。
    • obj3
      • obj3obj1 的深拷贝,obj3.data 以及 obj3.data 中的所有子对象(包括 obj3.data[1])都是全新的对象,与 obj1 及其子对象在内存中完全独立。所以修改 obj1.data[1][0] 不会影响 obj3.dataobj3.data[1][0] 仍然为 2 。
  2. 内存占用情况
    • obj1
      • obj1 本身占用一定内存,其 data 属性是一个列表对象,列表对象本身占用一定内存,列表中的第一个元素 1 占用一个整数的内存空间,第二个元素是一个子列表 [2, 3](修改后变为 [4, 3]),子列表本身占用一定内存,子列表中的元素分别占用整数的内存空间。
    • obj2
      • obj2 本身占用一定内存,其 data 属性是一个新的列表对象,占用一定内存。列表中的第一个元素 1 占用一个整数的内存空间,第二个元素与 obj1.data[1] 是同一个子列表对象(修改后变为 [4, 3]),所以这部分内存占用与 obj1.data[1] 共享。
    • obj3
      • obj3 本身占用一定内存,其 data 属性是一个全新的列表对象,占用一定内存。列表中的第一个元素 1 占用一个整数的内存空间,第二个元素是一个全新的子列表 [2, 3],子列表本身占用一定内存,子列表中的元素分别占用整数的内存空间,与 obj1obj2 的内存空间完全独立。

示例代码(Python)如下:

import copy


class MyClass:
    def __init__(self, data):
        self.data = data


obj1 = MyClass([1, [2, 3]])
obj2 = copy.copy(obj1)
obj3 = copy.deepcopy(obj1)
obj1.data[1][0] = 4
print("obj1.data:", obj1.data)
print("obj2.data:", obj2.data)
print("obj3.data:", obj3.data)

这段代码运行后,可以直观看到 obj1obj2obj3data 属性的变化。