Python 函数调用的内存分析

 问题引入    :  为什么 局部变量无法在 函数体外部 访问??

函数在内存中的调用  :

1 age = 10
2 name = 'james'
3 
4 def info():
5   global age
6   gender = '男'
7   b = 20           #   只是为了方便下面 讲解,定义一个局部变量 内存(对于本代码没啥用)
8   age += 1
9   print("球星的名字是 :  ", name)
10   print("球星的年龄是 : ", age)
11   print("球星的性别是 : ", gender)
12 
13  print(age)
14  print(name)
15 
16 
17  info()
18  print(age)
 
展示结果 :
球星的名字是 :   james
球星的年龄是 :  11
球星的性别是 :  男
11
james
11

   需要用到上面的代码 协助 我们讲解 ( 不需要 代码 本身 ) 

                 

              现在换个角度,从内存的角度来分析整个程序

           ( 因为所有代码本质都是在内存中跑起来的! 所以我们从内存角度来分析下上示问题!)

           ( 当然了,在这里讲的内存 是指 运行内存  !!)

              内存是分为好几个区的,在这里,我们不多说,我们摘几个和本题相关的区来讲 :

                 :   stack 

                        #    它是内存中最大的区域; 它的结构是树形结构!

                        #    函数的本质其实就是 堆内存,它就存储在 堆内存中!! 

                        

                : heap 

                        #    每个程序开始运行的时候,就会分配一个 运行栈 让程序去执行

                              它的内存空间不会太大( 运行代码! )

                        #    整个运行栈就可以简单的理解为 整个程序的运行轨迹 ! 

                        #    先进后出

    函数调用  :

                        从内存角度来说,函数调用 其实本质就是 压栈操作( push )

                        即  :  把数据推入到 栈 中去 !!

                      Python 函数调用的内存分析_第1张图片

                       首先,强调上图几点 :

                        #   在上图 是把 基本数据类型放到了 栈里,这是为了更方便理解,其实,基本数据

                             类型是在小整形缓冲区里放着,不想引入,但不妨碍我们理解内存分析!!

                        #    栈  真正的结构中 恰好是 栈底在上面,栈顶在下面,但为了方便理解(先进后

                              出)我们就反着画了下(  把 age 画在了 底部----我们意识里的底部,其实不是

                              栈真正意义上的底部) 

                              你看,按照现在画的,就很好理解 先进后出(你想象成一个瓶子)了, age 是 

                              先放进去的,你要想把它取出来就得先把 name 取出来,这就是先进后出(尽

                              管 真正的栈的结构不是这样!)  

                        解释下,上图 ( 解释下 最上面 代码 的执行逻辑 )

                        #    当 程序(最上面的代码) 开始运行时,就会 往栈里压数据,所以就有 整个运

                              行栈就是 整个程序的运行轨迹这么一说!

                        #     首先,程序执行第一行代码,有一个全局变量 age ,所以就会把 age 存到

                             (压) 栈里去;  接着 运行 第二行代码,即 把 name 也存到(压栈) 栈里面

                               去; 接着程序继续运行,注意, 4 到 11 行代码运行后,堆里是会有一个函数

                               的引用,但并不会自动就执行了,因为这一串并没有到栈里去,因为函数是要

                               调用的,调用才会执行属于函数体的代码,因此,当程序来到 17  行时,开始

                               进行函数调用!!    所以,也就有了 函数调用的本质其实就是 压栈操作!当

                               压栈操作完成后,在 栈内存 中 便有了一块 属于 函数的内存( 为了方便区

                               分,我用 红色框框 圈起来,因此在 栈内存中的 函数内存 便 执行 函数体里的

                               代码( 这里也自然时 局部变量 被声明,被执行的地方 )

                               当 函数体里的代码 一行一行的执行完,便会回到  17 行,你函数 从那里调用

                               的最后就回到那里去。

                               至此,整个 函数调用彻底结束!!(  这也叫做  出栈  /   弹栈  ) 

                                

                         

 

                        当 函数调用结束 (也就是 函数执行完毕) 其本质 即 : 弹栈/出栈操作( pop )

                        即 : 函数在调用完成后,会退出内存(也就是 栈里不会有函数)!!

                                 而 函数里的局部变量就是在刚才 释放的内存里存储的,你现在,函数执行完

                                 成释放了,出栈了; 因此,在 栈里必然再找不到 局部变量了 ( 你局部变量被

                                 存储的内存都没了,怎么可能还能看到 局部变量呢??)

                             Python 函数调用的内存分析_第2张图片

                                  

                              因此 ,函数在调用完成后,内存是会被回收的!!

               拓展  :  

                         内存溢出    内存不够用了 

                                               比如,我分配了一个大小,结果数据太大存不下,比如我分配了一个

                                               10 个字节的大小,结果你数据是 11 个字节,这就是数据太大存不下

                                                了,那怎么办?  只能存  10 个 剩余那 1 个 就会被溢出,那么,这

                                                 样就有可能导致 数据出问题!! 

                                        

                         内存泄漏    垃圾内存没有得到回收         

              

你可能感兴趣的:(PYTHON,1024程序员节,python)