3.引用赋值、浅拷贝和深拷贝

对象和对象之间,通过内存的操作存在各种各样的关系,那么这些关系都有什么样的特点又

是怎么分配的呢?

这里就要说到对象的内存分配,对象的引用赋值、对象的深浅拷贝了

3.1.对象的内存分配

对象的创建,依赖于申请的内存空间中数据的加载,对象在内存中的创建过程依赖于三部分

内存处理:对象分配内存地址、引用变量分配内存地址、对象和引用变量之间的关联

参考代码:

# coding=utf-8
from memory_profiler import profile


class Person():
    '''自定义类型'''
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
 
@profile(precision=10)
def main():
    '''入口函数'''
    p = Person("tom", 18, "男")
    print(p)
    p2 = Person("tom", 18, "男")
    print(p)
 

if __name__ == "__main__":
    # 运行代码
    main()

执行结果为:

D:\python36\python.exe C:/Users/leeking/PycharmProjects/python/内存分析/demo06.py
<__main__.Person object at 0x0000001771FE7A58>
<__main__.Person object at 0x0000001771FE7A58>
Filename: C:/Users/leeking/PycharmProjects/python/内存分析/demo06.py

Line #    Mem usage    Increment   Line Contents
================================================
    14  15.8281250000 MiB  15.8281250000 MiB   @profile(precision=10)
    15                             def main():
    16                                 '''入口函数'''
    17  15.8320312500 MiB   0.0039062500 MiB       p = Person("tom", 18, "男")
    18  15.8359375000 MiB   0.0039062500 MiB       print(p)
    19  15.8359375000 MiB   0.0000000000 MiB       p2 = Person("tom", 18, "男")
    20  15.8359375000 MiB   0.0000000000 MiB       print(p)

内存分配图解:

由于对象的创建,是将堆内存中创建的对象的地址临时存储在栈内存中的变量中,那么在程

序中如果要在多个地方使用一个对象数据时应该怎么办呢?一般想到的都是将对象像文件

一样复制一份不就好了。

PYTHON 中对于这样的情况,有三种不同的操作方式

⚫ 如果程序中多个不同的地方都要使用同一个对象,通过对象的引用赋值,将同一个对象

赋值给多个变量

⚫ 如果程序中多个不同的地方都要使用相同的对象数据,通过对象的拷贝完成数据的简单

复制即可,对象中的包含的数据要求必须统一

⚫ 如果程序中多个不同的地方使用相同的而且独立的对象数据,通过对象的深层次的复制

将对象的数据完整复制成独立的另一份即可

3.2. 对象的引用赋值

对象的引用赋值,可以将对象的内存地址同时赋值给多个变量,这多个变量中存放的都是同

一个对象的引用地址,如果通过一个变量修改了对象内容,那么其他变量指向的对象内容也

会同步发生改变.

例如:

 

在上面,我们定义了一个列表和一个变量,并把变量a指向这个列表的内存地址,之后通过赋值,把a的值赋给b,即将这个内存地址也赋值给b.此时a与b所指向的内存地址一样.所以a与b的值也都相同.我们通过改变a的值,可以发现b的值也跟着发生了变化.

对象的引用变量的赋值,并不是对象的复制或者备份,而仅仅是将对象的地址存储在多个变

量中方便程序操作。

 

可以看出,我们通过引用赋值操作一个自定义类型,也能起到上面的作用

 

注意:PYTHON 中所谓对象的引用赋值,针对的是可变类型,不论是组合数据类型或者自定

义 class 类型,都具备引用赋值的操作;但是不适合不可变类型,不可变类型的引用赋值

操作有只读不写的特征,一旦通过变量重新赋值就会重新指向新的引用对象

 

上面的代码操作不可变数据类型时,应为不可变数据类型的特点,所以在改变a的值时,a会重新指向一个内存地址,所以这个时候的b的值不会发生改变

3.3. 对象的浅拷贝

对于程序中对象的拷贝操作,除了前面介绍的引用赋值操作可以完成同一个对象在程序不

同位置的操作,这里的浅拷贝更是一种对象的临时备份,浅拷贝的核心机制主要是赋值对象

内部数据的引用

PYTHON 内建标准模块 copy 提供了一个 copy 函数可以完成

在上面我们可以看出,通过a浅拷贝出的b,两者的内存地址是不同的.所以浅拷贝就是重新复制了一份a中的值,但是,浅拷贝复制的列表中的值所指向的静态区内存地址是相同的.即id(a[4])与id(b[4])的内存地址是相同的,所以操作a[4]中的数据,那么b[4]中的数据也会发生变化

4.5.对象的深拷贝

和对象的浅拷贝不同,对象的深拷贝,是对象数据的直接拷贝,而不是简单的引用拷贝

主要是通过 PYTHON 内建标准模块 copy 提供的 deepcopy 函数可以完成对象深拷贝

深拷贝则是将所有与的数据都重新复制一份,所以这个时候的id(a[4])与id(b[4])的值不同,即内存地址不同,所以修改a[4]的值,就不会影响b中的值

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值