Python学习记录 对象的浅拷贝和深拷贝

2022.08.18 DAY34

特殊属性
  • Python对象中包含了很多双下滑线开始和结束的属性,这些是特殊属性,有特殊用法。

      obj.__dict__    对象属性字典
      obj.__class__   对象所属的类
      class.__bases__ 类的基本元祖(多继承)
      class.__base__  类的基类
      class.__mro__   类层次结构
      class.__subclasses__()  子类列表
    
对象的浅拷贝和深拷贝
  • 变量的赋值操作
    • 只是形成两个变量,实际还是指向同样一个对象,
  • 浅拷贝
    • Python中的拷贝一般都是浅拷贝。
    • 浅拷贝,对象包含的子对象内容不拷贝。所以,源对象和拷贝对象都会引用同一个子对象。
  • 深拷贝
    • 使用copy模块的deepcope函数,递归拷贝对象中包含的子对象。源对象和拷贝对象所有的子对象也不同。

测试代码:

import copy

class MobilePhone:
    def __init__(self, cpu, screen):
        self.cpu = cpu
        self.screen = screen

class CPU:
    def calculate(self):
        print("算你个!@#¥%……&*")
        print("CPU对象:", self)

class Screen:
    def show(self):
        print("显示一个好看的画面,亮瞎你的钛合金大眼")
        print("Screen对象:", self)

def test():
    c1 = CPU()
    c2 = c1
    print(c1)
    print(c2)

    s1 = Screen()
    m1 = MobilePhone(c1, s1)
    m2 = copy.copy(m1)
    print(m1)
    print(m1.cpu)
    print(m1.screen)

    print(m2)
    print(m2.cpu)
    print(m2.screen)

    m3 = copy.deepcopy(m1)
    print(m3)
    print(m3.cpu)
    print(m3.screen)


if __name__ == "__main__":
    test()

运行结果:

<__main__.CPU object at 0x000001A235B88400>
<__main__.CPU object at 0x000001A235B88400>

<__main__.MobilePhone object at 0x000001A235B72340>
<__main__.CPU object at 0x000001A235B88400>
<__main__.Screen object at 0x000001A235C01D00>

<__main__.MobilePhone object at 0x000001A235C97FD0>
<__main__.CPU object at 0x000001A235B88400>
<__main__.Screen object at 0x000001A235C01D00>

<__main__.MobilePhone object at 0x000001A235CA5430>
<__main__.CPU object at 0x000001A235CE1AC0>
<__main__.Screen object at 0x000001A235CE1B50>
组合
  • 实现一个类拥有另一个类的方法和属性。

测试代码:

# 测试组合

class A1:
    def say_a1(self):
        print("a1:", self)

class B1:
    def __init__(self, a):
        self.a = a

def test():
    a1 = A1()
    b1 = B1(a1)
    b1.a.say_a1()


if __name__ == "__main__":
    test()

运行结果:

a1: <__main__.A1 object at 0x0000024CFE288400>
<think>好的,我现在需要回答用户关于浅拷贝深拷贝的问题。首先,我得回忆一下这两个概念的基本定义。浅拷贝深拷贝主要涉及到对象复制的层次不同。浅拷贝只复制对象本身,而不复制对象内部的子对象,而深拷贝会递归复制所有子对象,对吧?不过具体细节可能还需要进一步确认。 然后,我需要考虑它们的区别。比如,对于包含可变对象的复合对象,比如列表中的列表,浅拷贝后的对象对象中的子列表是否指向同一个内存地址。这时候修改其中一个会影响另一个,而深拷贝则不会。这个例子是不是常见?应该用代码示例来说明会更清楚。 接下来是应用场景。浅拷贝适用于对象内部元素不可变的情况,比如元组或者字符串,这样即使共享子对象也没问题,还能节省内存。而深拷贝用于对象内部有可变子对象的情况,比如嵌套列表或字典,需要完全独立的副本时使用。这部分需要举具体的例子,比如配置字典的拷贝,或者递归数据结构。 然后,用户可能还想知道在不同编程语言中的实现方式,但用户提到的是Python,所以应该以Python为例。Python中可以用copy模块的copydeepcopy函数。这时候可以写一个简单的代码示例,展示浅拷贝深拷贝的不同效果。 另外,需要注意哪些情况下必须使用深拷贝。例如,当对象之间存在循环引用时,浅拷贝可能会导致问题,而深拷贝可以处理这种情况。不过这可能比较复杂,是否需要提及?或者保持回答简洁? 还要检查是否有常见的误区,比如认为浅拷贝只是复制顶层对象,而深拷贝复制所有层。这个是正确的,但需要明确说明。 然后,生成相关问题。用户可能需要了解如何选择拷贝方式,或者在不同语言中的实现差异,或者拷贝在并发编程中的应用。但根据用户的问题,可能更关注区别应用实例,所以相关问题可以围绕这些方面展开。 现在,需要确保回答结构清晰,分点说明区别,应用实例,并提供代码示例。同时,引用部分需要自然地添加标识,但用户提供的引用中并没有具体的引用来源,可能需要检查是否有必要添加,或者按示例处理。 最后,检查LaTeX格式是否正确,所有行内数学表达式用$...$,独立公式用$$...$$,但这个问题可能不涉及数学公式,所以可能不需要。但如果有变量或代码中的符号,需要用代码块包裹。 总结一下,回答的结构应该是: 1. 定义浅拷贝深拷贝 2. 区别对比,可能用表格或分点 3. Python中的实现(copydeepcopy) 4. 应用场景举例 5. 代码示例展示不同行为 6. 相关问题生成 需要确保语言简洁,使用中文,代码正确,并且分点清晰。同时,用户的问题可能更关注实际应用,所以多举例子会更好。</think>### 浅拷贝深拷贝的区别及应用实例 #### 1. 基本概念 - **浅拷贝**:仅复制对象的**顶层结构**,若对象包含子对象(如列表嵌套列表),则子对象仍为原对象的引用[^1]。 - **深拷贝**:递归复制对象的**所有层级**,生成完全独立的新对象,与原对象无任何引用关联。 #### 2. 核心区别 | 特性 | 浅拷贝 | 深拷贝 | |--------------|----------------------------------------------------------------------|----------------------------------------------------------------------| | 复制层级 | 仅顶层 | 所有层级 | | 内存占用 | 较小(共享子对象) | 较大(完全独立) | | 修改影响 | 子对象修改会影响原对象 | 子对象修改与原对象无关 | | 适用场景 | 子对象不可变(如元组、字符串)或无需完全独立 | 子对象可变且需隔离(如配置字典、嵌套结构) | #### 3. Python实现示例 ```python import copy # 原始对象(包含可变子对象) original = [[1, 2], [3, 4]] # 浅拷贝 shallow = copy.copy(original) shallow[0][0] = 99 print(original) # 输出 [[99, 2], [3, 4]],原对象被修改 # 深拷贝 deep = copy.deepcopy(original) deep[1][0] = 88 print(original) # 输出 [[99, 2], [3, 4]],原对象不受影响 ``` #### 4. 应用场景 - **浅拷贝** - 快速创建配置模板(子对象为默认值且不可变) ```python default_config = {'threshold': 0.5, 'options': ('log', 'debug')} new_config = copy.copy(default_config) # 安全,因元组不可变 ``` - **深拷贝** - 多线程环境下操作独立数据副本 - 机器学习中防止训练数据被意外修改 ```python dataset = {'features': [[...]], 'labels': [...]} safe_copy = copy.deepcopy(dataset) # 完全隔离训练与测试数据 ``` #### 5. 注意事项 - **循环引用问题**:深拷贝可通过`memo`字典记录已复制对象解决循环引用[^2] - **性能代价**:深拷贝递归过程对复杂对象(如树形结构)可能产生较高时间复杂度
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值