SDET / SWE · Technical Fundamentals

TikTok Python 拷贝:赋值、浅复制与深复制的对象图

用嵌套列表和共享引用辨认别名,解释deepcopy保留内部共享以及循环处理。

题目重点:用嵌套列表和共享引用辨认别名,解释deepcopy保留内部共享以及循环处理。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 示例基于Python标准copy模块,讨论一般容器对象;外部资源复制需自行定义。
  • deepcopy不是数据库快照或多线程原子冻结。

解题路线

  1. 赋值b=a只让两个名字绑定同一对象,没有复制;对其中任意名字做可变操作都影响同一个对象。对象身份与值相等是不同判断。
  2. 浅复制建立新外层容器,但元素仍引用原来的对象;新增外层元素不影响另一外层,修改共享内层list则双方都看到。只测外层is不同不足以证明隔离。
  3. 深复制递归复制可复制的对象图,并用memo避免重复遍历与循环无限递归。原图两处指同一子对象,复制后通常仍指同一份新子对象,保留图内共享关系。
  4. deepcopy并不是复制所有东西:函数、类或外部资源有专门规则,文件连接/锁/会话需要业务明确,不能把它当任何对象都可序列化的魔法。自定义__deepcopy__也可改变行为。
  5. 缓存和配置读写边界要按所有权选策略。完全共享不可变数据最简单;只读对象加copy-on-write可减少全量深复制,但嵌套可变成员仍需处理。
  6. 并发中复制期间被另一线程修改可能得到混合视图,要用锁、不可变版本或业务快照协议;deepcopy解决引用隔离,不自动提供时点一致性。

手动走一遍

a=[[1]];b=a,c=copy.copy(a),d=copy.deepcopy(a)。a[0].append(2)后b/c都看到[[1,2]],d仍[[1]]。若a=[x,x],深复制后两项依然共享同一个新的x副本,不是彼此独立的两个副本。

规模与取舍

浅复制容器n项通常O(n)时间空间,成员对象不递归计;深复制按遍历对象图节点/边及自定义逻辑计,通常O(V+E)时间空间,循环由memo处理,深度带来栈限制。

易错点与追问

容易失分的边界

  • 赋值称浅复制。
  • 只检查最外层身份。
  • 认为deepcopy会消除内部共享关系。

继续深挖

  • 如何自定义__deepcopy__?
  • 循环图怎样保持结构?
  • 并发快照如何保证一致时点?

技术参考

  • Python copy:技术语义参考,具体题目按本文约定。
✓已复制微信号!