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

posted on 2019-12-20 20:38  King-Penguin  阅读(960)  评论(0编辑  收藏  举报

导航