python 释放变量占用内存 python清除变量内存_作用域


了解内存管理可以帮助您编写高效的Python代码。尽管您可能无法控制内存分配,但是您可以优化程序来更好地分配内存。

在深入研究之前,请记住:在python中,一切都是对象。

与C,C ++或Java不同,值存储在内存中,并且变量指向该内存位置。


python 释放变量占用内存 python清除变量内存_作用域_02

C中的内存分配


在python中,整个对象存储在内存中,对象可以是整数、字符串或列表,以及指向对象的变量。困惑吗?

为了理解,让我们了解python对象的作用!

内存中的PyObject:

  1. 类型:整数、字符串、浮点数等
  2. 引用计数:绑定到该对象的引用的数量
  3. 值:值/数据/信息


python 释放变量占用内存 python清除变量内存_python 删除变量_03

PyObject(a = 200)


因此,每当您创建一个变量时(比如a = 200),就会在内存中创建一个新的PyObject,它的ref count被设置为1,变量“a”指向它。

但是什么是ref count呢?

让我们举个例子来理解它。我们有一个类型为integer、值为200的变量“a”。假设我需要另一个名为“b”的变量,其类型为integer,值为200。你已经创建了两个这样的变量

因此,您已经创建了两个这样的变量

a = 200

b = 200

现在,您可能在猜测,对于变量“a”和“b”,内存中必须有2个对象。但事实并非如此。“a”和“b”指向同一个对象。


python 释放变量占用内存 python清除变量内存_python 释放变量占用内存_04

变量a和b引用相同的PyObject


让我们通过Python代码来验证这一点。

>>> a=1>>> b=1>>> c=2>>> id(a)94147440556736>>> id(b)94147440556736>>> id(c)94147440556768>>>

如您所见,变量“ a”和“ b”具有相同的id(内存位置),因此表示相同的对象,而c具有不同的id值。因此,当前在内存中有两个python对象。

现在,如果我们为“ a”分配一个新值,即a = 3。

>>> a=3>>> id(a)94147440556800>>> id(b)94147440556736>>>

现在, “ a”指向一个新对象,而 “ b”仍然指向同一对象。

但是让我们考虑这个例子。

>>> a=1>>> b=a>>> id(a)94147440556736>>> id(b)94147440556736>>>

在此示例中,a = 1,但“ b”的值为“ a”。当我们更改“ a”的值时,是否也会影响“ b”?让我们来看看。

>>> a=1>>> b=a>>> id(a)94147440556736>>> id(b)94147440556736>>> a=3>>> id(a)94147440556800>>> id(b)94147440556736>>>

“ a”现在指向新对象,但 “ b”仍然指向旧对象。

但这是为什么呢?

因为“b”并不直接指向变量“a”,而是指向变量“a”的对象。这就是ref count的作用,它跟踪指向它的变量的数量。

另一个有趣的问题是,如果PyObject的引用ref count变为零,将会发生什么呢?

在此之前,让我们了解如何删除对对象的引用。

1.del

Python的内置del关键字可帮助我们删除这些指向对象的引用。实际上,有些人认为del从内存中删除了对象,事实并非如此。

因此,您可以像这样使用del删除引用。

>>> a=2>>> id(a)94147440556768>>> del a

2. 超出范围

一旦超出范围,对象的引用将自动删除。

>>> def scope():...     x=1...     print(id(x))... >>> scope()94147440556736>>>

让我们以上面的代码为例,变量“ x”的对象在scope()函数中ref count为+1,但是当解释器离开此函数作用域时,PyObject的ref count将减1,因为“ x”是一个局部变量,只对它的函数有作用域。

这就是为什么python不鼓励使用全局变量的原因之一,因为全局作用域中的变量可以应用于整个程序。

3.将新对象分配给变量。

将新对象分配给现有变量时。前一个对象的ref count减1。

>>> a=1>>> id(a)94147440556736>>> a=2>>> id(a)94147440556768>>>

现在,回到前面的问题,当对象的ref count为0时会发生什么。它是否保留在内存中呢?

一旦对象的ref count变为0,垃圾收集器就会将其从内存中删除。