美文网首页
第021篇:内存管理与拷贝

第021篇:内存管理与拷贝

作者: yydafx | 来源:发表于2019-11-27 19:14 被阅读0次

    1、内存管理

    1.1、内存管理基础(C语言)
    •  内存分为栈区间和堆区间,栈区间的内存是系统自动申请自动释放;堆上的内存需要程序通过调用 malloc 函数去申请,调用 free 函数去释放;
    •  高级语言(Java\C++\OC\Python)中的内存管理机制都是针对堆上的内存的管理进行自动化操作
    1.2、Python的内存管理机制

     1)内存的申请
     Python所有的数据都是存在堆中的,变量是保存在栈里面的,变量中保存的是保存在堆中的数据的地址。重新给变量赋值,会先在内存开辟新的内存保存新的数据,然后将新的数据的地址保存到变量。
     但是如果使用数字或者字符串给变量赋值,不会直接开辟新的内存,而是检查内存有没有这个数据,如果有就直接将原来的数据的地址给变量。

     2)内存的释放(垃圾回收机制)
     再Python中一个数据对应的内存空间是否释放,就看这个数据的引用计数是否为0;如果引用计数为0,数据对应的内存就会被自动释放。
    循环引用问题:Python的垃圾回收机制会自动出来循环引用问题
    增加引用计数:增加数据的引用(让更多的变量来保存数据的地址)
    减少引用计数:减少引用(让更多的引用去保存新的数据)

    代码演示

    # 使用数字给变量赋值
    a = 100
    print(id(a))    # 1418346288
    a = 200
    print(id(a))    # 1418347888
    
    b = 100
    print(id(b))    # 1418346288
    b = 100
    print(id(b))    # 1418346288
    
    # 使用字符串给变量赋值
    e = 'abd'
    print(id(e))    # 18607520
    e = 'abd'
    print(id(e))    # 18607520
    
    
    f = 'abd'
    print(id(f))    # 18607520
    f = 'abb'
    print(id(f))    # 18651264
    
    c = []
    print(id(c))
    c = []
    print(id(c))
    
    d = {'a': 10}
    print(id(d))
    d = {'a': 10}
    print(id(d))
    
    import sys
    
    list1 = [1, 2, 3]
    print(sys.getrefcount(list1))   # 查看引用计数
    
    list1 = [1, 3, 2]
    list2 = [list1, 10, 20]
    list1.append(list2)
    print(list1)
    print(list2)
    

    2、拷贝

    1.直接赋值

     用一个变量直接给另外一个变量赋值的时候赋的地址;赋值后两个变量保存的是同一个数据的地址

    1.直接赋值

     用一个变量直接给另外一个变量赋值的时候赋的地址;赋值后两个变量保存的是同一个数据的地址

    2.浅拷贝

     复制原数据产生一个新的数据(值和原数据一样,地址不同),然后将新的数据的地址返回; 如果有子对象,子对象不会复制

     话不多说,直接看代码

    from copy import copy, deepcopy
    
    
    class Dog:
        def __init__(self, name, color='黄色'):
            self.name = name
            self.color = color
    
        def __repr__(self):
            return '<%s __id: %s>' % (str(self.__dict__)[1:-1], id(self))
    
    
    class Person:
        def __init__(self, name, age=10, gender='男', dog=None):
            self.name = name
            self.age = age
            self.gender = gender
            self.dog = dog
    
        # 这个函数会在打印当前类的对象的时候自动调用; 函数的返回值就是打印的结果
        # 返回值是字符串
        def __repr__(self):
            return '<%s __id: %s>' % (str(self.__dict__)[1:-1], id(self))
    
    
    # 1.直接赋值
    # 用一个变量直接给另外一个变量赋值的时候赋的地址;赋值后两个变量保存的是同一个数据的地址
    print('直接赋值')
    p1 = Person('小明', dog=Dog('大黄'))
    p2 = p1    # 赋值后p1和p2指向是同一个Person对象
    print('p1:', p1)
    print('p2:', p2)
    p1.gender = '女'
    p1.dog.color = '白色'
    print('p1:', p1)
    print('p2:', p2)
    
    
    # 2.浅拷贝
    # 复制原数据产生一个新的数据(值和原数据一样,地址不同),然后将新的数据的地址返回; 如果有子对象,子对象不会复制
    print('=============浅拷贝==============')
    p1 = Person('小明', dog=Dog('大黄'))
    p2 = copy(p1)
    print(p1)
    print(p2)
    p1.gender = '女'
    p1.dog.color = '白色'
    print('p1:', p1)
    print('p2:', p2)
    
    # 3.深拷贝
    # 复制原数据产生一个新的数据(值和原数据一样,地址不同),然后将新的数据的地址返回; 如果有子对象,子对象也会复制
    print('=============深拷贝===========')
    p1 = Person('小花', dog=Dog('大黄'))
    p2 = deepcopy(p1)
    print('p1:', p1)
    print('p2:', p2)
    p1.gender = '女'
    p1.dog.color = '白色'
    print('p1:', p1)
    print('p2:', p2)
    

    相关文章

      网友评论

          本文标题:第021篇:内存管理与拷贝

          本文链接:https://www.haomeiwen.com/subject/wjcmwctx.html