02 – Python101 – 内存

Python其中一个特点就是将所有的变量都认作Object,不像Java会分primitive或non-primitive,Python所有的内容都可以被假设看作non-primitive。

(这句是给习惯了Java说法的孩子们看的因为这样Java选手就直接能明白了。如果你目前还一头雾水,直接往下看就好了!)

Python内存使用方式 – 理论:

首先我们来通过理论来解释Python中每一个变量是怎么被内存存储的。这一部分可能有一点点晦涩,但我在下一段落包含了一个更生动的解释 😛

假设我们有一行代码:

a = 1

在执行这行代码时,python会让你的电脑内存开辟一小块地方存放这个整型值(int) 1。这个id具体可以通过执行 id(a) 来获得,但为了方便交流与表示,我们用id1来代替。在分析Python内存时,我们一般都用id1,id2等来表示不同内存空间的id,而不用系统给他设定的名字(十几位随机打乱的数字根本没人记得住啊喂)。通过图像我们可以这么表示:

这张图表示命名为 a 的这个变量指向内存中id1位置的值,这个值得类型是int整型。

如果我们执行:

a = 1
a = 2

我们就可以画成:

在a=1的时候,a指向id1,执行a=2的时候,a就不再指向id1的内容,而是指向新建的id2中的2。

如果我们执行:

a = 1
b = a

则可以画成:

首先a变量指向id1咱们已经介绍过了。第二行的b=a这时做的就是让b指向和a一样的id。

这就是Python赋值语句(=)的规则:永远让左侧的变量指向右半部分指向的id。由于一个具体的值不存在已有的id,所以当python给变量赋值成一个具体值(1, 2.0, “Hi”, Object)的时候,都会让那个变量指向一个全新的,存放那一个具体值的内存id。

这个规则还有另外一个特点:如果右侧进行了一个运算(加减乘除等等),由于内存中本来没有存储过那个运算结果,所以也会新建一个id存放运算结果,并让左侧的变量指向那个新的id。

现在咱们来看一个结合了以上特性的代码:

a = 1
b = 2
a = b

这就可以画成:

前两行的变量指向都已经在之前的部分讲过了,而最后一步(a = b)用绿色标注出来的,此时a被要求指向b所指向的内存id,所以初始的id1就被挤掉了,执行完代码后的变量a就会变为指向id2,值为2。在编程中,此时我们称 a 和 b 互相 alias。

内存运用 – 一个生动一些的解释:

假设你是a,你要去一个滑雪场滑雪。滑雪场的换衣间是内存,而每一个柜子就是一个内存中的id。你所需要的滑雪用具会在你跟老板要了之后被放在某个柜子里,而老板会给你打开那个柜子的钥匙,且你只能有一把钥匙;滑雪用具有无数种组合,你可能需要1套餐,也可能需要2套餐,甚至可能需要x套餐。套餐的命名什么都有,并且这些套餐的命名及内容符合所有数学运算(这必然不可能在现实发生,但我们就这么假设着)。现在我们再来看之前的每一个例子:

a = 1

简单明了,你跟老板说要一个1套餐,老板把一份1套餐的滑雪用具放在了id1的柜子里,并给你打开id1柜子的钥匙。

a = 1
a = 2

你跟老板预订了一份1套餐之后发现不太好用,决定换用2套餐。当场清理id1柜子太麻烦了,老板于是把一份2套餐帮你放在了id2的柜子里,给了你id2柜子的钥匙,然后把id1的钥匙拿走了,因为你不再需要原来的1套餐。

a = 1
b = a

此时你的朋友b也来到了滑雪场,他和你都想使用1套餐滑雪,但再让老板开一份1套餐太贵了,所以b决定和你共用一套器具。这样b也能用到1套餐。老板很大方,于是给了b一份打开id1的钥匙,方便你俩随时取用。不必担心同时要用的问题,电脑内存用的都飞快,即使每个人轮流用很小一段时间,电脑也能极快的让你俩都体验到1套餐的乐趣。

a = 1
b = 2
a = b

你先到了滑雪场选了一份1套餐,b到滑雪场之后学了一份2套餐。你发现2套餐比你的要好用许多,于是找老板退了1,跟b共享一份2套餐。老板于是收走了你id1的钥匙,给了你id2的钥匙。这时,你和 b 就产生了Alias — 你们两拿着打开同一个柜子的钥匙

好了下面就是新的问题了:

a = 1
b = a
a = 2

如果是这样,b最终会是什么值(用什么套餐)呢?想一想,鼠标滑到下方蓝色部分查看答案:

为什么嘞,b不应该等于a嘛? 还是用滑雪的例子!你先选择了1号套餐,b来了之后觉得1够用,于是和你共享一套1。但这个时候,你觉得似乎1不太够用了,就跟老板重新开了一套2套餐。于是老板决定让你用2套餐,于是给你开了一个新的id2柜子,并给了你id2的钥匙,收回了id1的。此时b仍然用着id1的钥匙,而你只有id2的钥匙了(一开始我们假设过,一个人只能拿一把钥匙)。于是b会继续用着id1柜子的东西,你会用id2柜子里的器械。

最后,还有一种可能。在上文的基础上,你的另一个朋友 c 来了,既想用你的器械又想用 b 同学的器具。代码如下:

a = 1
b = a
a = 2
c = a + b

这个时候,他就不好要求老板既给他id1的钥匙又给他id2的钥匙了。第一,他只能拿着一把钥匙;第二,即使他能拿两把钥匙,他也需要每次打开两个柜子,非常的麻烦。既然我们已经规定,所有的套餐的名字和内容都符合数学运算,那我们可以知道1套餐+2套餐=3套餐。于是老板就开了一个新的id3柜子,存放3套餐,并给了c 打开id3柜子的钥匙。现在c指向的就是id3了。于是 c = 3,因为 3 = 1 + 2,但 c 指向的是 id3,是一个全新的id。同样的道理也适用于函数增加一个常量:

a = 1
id1 = id(a)
a = a + 1
id2 = id(a)
#id(a)会返回a在内存中的id。此时的id1不等于id2。

这样的解释是不是更加的直观一些呢?这就是Python对于内存的应用了!希望能帮你更进一步的理解这些概念!

本位由JamesChenS编写,未经授权禁止转载!可以直接用外链哦~

Scroll to Top