• 2.Python 赋值与内存


     

    定义变量和赋值就是系统处理内存的过程和问题,这篇文章分别从申请和释放内存两部分讨论

     

    一、申请内存

     

    python定义一个变量时,会为变量的对象申请一个内存,该变量会存储指向该对象内存中的地址

    这样的好处是复用共同内容对象,节省内存空间

    In [1]:
    name = 'admin'
    print("name=", name)
    
    name1 = name
    print("name1=", name1)
    
     
    name= admin
    name1= admin
    
    In [2]:
    name2 = 'admin'
    print("name2=", name2)
    
     
    name2= admin
    
    In [3]:
    print(id(name), name)
    print(id(name1), name1)
    print(id(name2), name2)
    
     
    2951857458848 admin
    2951857458848 admin
    2951857458848 admin
    
     

    如图:定义了name变量,赋值为“admin”,然后将name赋值给name1,则name1拥有了与name相同的值。再定义另一个变量name2,将name2的值设值为“admin”。也就是name,name1和name2值都为“admin”。则系统赋值运行的过程如下:

    1.系统会申请一个内存,存放“admin”

    2.将name,name1和name2共用“admin”这个内存

    In [4]:
    name2 = name
    print(name == name2)
    print(id(name) == id(name2))
    
     
    True
    True
    
    In [5]:
    name2 = "admin1"
    print(id(name), name)
    print(id(name2), name2)
    
    print(name == name2)
    print(id(name) == id(name2))
    
     
    2951857458848 admin
    2951857622744 admin1
    False
    False
    
     

    上面两块代码验证了在python系统中,变量会共用相同的值的内存。

    1.当name2的值与name的值为“admin”时,name2与name对象的内存地址相同。

    2.当name2的值改变为“admin1”时,name2对象的内存地址将会改变了

     

    二、释放内存

     

    Python的内存管理主要有三种机制:引入计数机制、垃圾回收机制和内存池机制。

    引入技术机制:在python内部,通过引入技术来保持追踪内存中的对象,python内部记录对象有多少个引用,即引用计数,当对象被创建使就创建一个引用计数,当对象不再需要时,这个对象的引用计数为0时,它将被垃圾回收。

    垃圾回收机制:当内存中不再使用该内存部分时,垃圾收集器就会把它们清理掉。它会去检查引用计数为0的对象,然后清除其所在的内存的空间。

    内存池机制:在Python中,许多时候申请的内存都是小块的内存,这些小块内存在申请后,很快又会被释放,由于这些内存的申请并不是为了创建对象,所以并没有对象一级的内存池机制。这就意味着Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python的执行效率。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。内存池的概念就是预先在内存中申请一定数量的,大小相等的内存块留作备用,当有新的内存需求时,就先从内存池中分配内存给这个需求,不够了之后再申请新的内存。这样做最显著的优势就是能够减少内存碎片,提升效率。内存池的实现方式有很多,性能和适用范围也不一样。

    下面通过三个步骤分析内存管理和释放的过程:

     

    步骤1:将name2和name1的值都更变为“admin1”,可以发现,name1和name2的对象都为“admin1”,name1和name2打印出来的对象内存地址都是相同的。而name对象为“admin”,name打印出来的内存地址与另外两个不同。

    In [6]:
    name2 = 'admin1'
    
    In [7]:
    name1 = name2
    print(id(name1), name1)
    print(id(name2), name2)
    
    print(id(name), name)
    
     
    2951857622744 admin1
    2951857622744 admin1
    2951857458848 admin
    
     

    步骤2:将name的对象也更变为“admin1”,再从新打印发现name,name1和name2的地址一样了。

    In [8]:
    name = 'admin1'
    print(id(name1), name1)
    print(id(name2), name2)
    print(id(name),name)
    
     
    2951857622744 admin1
    2951857622744 admin1
    2951857622744 admin1
    
     

    步骤3:重新申请name并复制为“admin”,打印出来后,发现该步骤中打印的name的对象内存地址与步骤一种打印name的内存地址变得不一样了。

    In [9]:
    name = 'admin'
    
    print(id(name1), name1)
    print(id(name2), name2)
    print(id(name),name)
    
     
    2951857622744 admin1
    2951857622744 admin1
    2951857632064 admin
    
  • 相关阅读:
    平时代码中用不到设计模式?Are you kidding me?
    关于kubernetes我们还有什么可做的?
    R语言︱文本挖掘——词云wordcloud2包
    描述性统计分析-用脚本将统计量函数批量化&分步骤逐一写出
    R语言读写中文编码方式
    R画图中英文字体完美解决方案
    Python 和 R 数据分析/挖掘工具互查
    关于ř与tableau的集成---- k均值聚类
    tableau 连接R语言
    小识Tableau
  • 原文地址:https://www.cnblogs.com/King-Penguin/p/12074967.html
Copyright © 2020-2023  润新知