交互模式下Python函数参数是怎么样传递的的问题

不管是不是「交互模式」,都是一样的。读操作时,规则是会依次查找:局部命名空间(当前函数、类方法中的局部变量、参数)如果多层嵌套的话的还会依次往外查全局命名空间(当前模块中的变量、函数、类)内置命名空间(Python 内置函数、变量)如果都没找到,抛 NameError 异常。p.s. 如果在某个命名空间中的任何地方存在对 x 的赋值,那么 x 就被认定是这个命名空间中的变量了,不会再往外查。「情景一」:在 great_function 中找不到 a外层由于手动给 a 赋了 2,所以存在 a;于是 a 的值就是 2「情景二」:在 greate_function 中由于前一行给 a 赋了 8,所以存在 a;于是 a 的值就是 8「情景三」:在 greate_function 中由于存在名为 a 的参数,所以存在 a;于是 a 的值就是参数 8
■网友
当你在一个程序中使用变量名时,python创建、改变或查找变量名都是在所谓的命名空间中进行的,也就是我们要说的变量的作用域。在代码中给一个变量赋值的地方决定了这个变量将存在于哪一个命名空间,也就是他的可见范围。
def之中的变量名和def之外的变量名并不冲突,一个在def之外被赋值(例如,在另外一个def之中或者在模块文件的顶层)的变量X与在这个def之中赋值的变量X是完全不同的变量。

所以我们看出,变量的作用域完全是由变量在程序文件中源代码的位置而决定,而不是由函数调用决定。
说了这么多概念,还是用例子说话吧!
x = 99def func(): x = 88print(x)func()print(x)8899这里就可以看出,在这个模块文件中:语句X=99,我们创建了一个名为X的全局变量(在这个函数所在的模块文件中可见),但是X=88这个赋值语句创建了一个本地变量X(只在def语句内是可见的)。
尽管这两个变量都是X,但是他们作用域可以把它们区别开来。实际上,函数的作用域有助于防止程序之中变量名的冲突,并且有助于函数成为更加独立的程序单元。

那下面我们接着展开具体介绍函数的四个作用域:LEGB,即L本地作用域,E内嵌作用域,G全局作用域和B内置作用域。
在一个函数中定义的是本地作用域,而模块(也就是一个xxx.py文件)中定义的是全局作用域。而内置作用域,我们使用时是直接使用变量名而不需要导入任何模块,比如一些内置的函数名:print等等

这里再强调一下python中所谓的全局作用域:
全局作用域的作用范围仅限于单个文件,别被全局二字所迷惑,这里的全局指的是一个文件的顶层的变量名仅对于这个文件内部的代码而言是全局的,在python中听到全局,你就应该想到模块二字。
变量名由模块文件隔开,并且必须精确的导入一个模块文件才能够使用这个文件中使用的变量名。
再说说本地作用域:每次对函数的调用都创建一个新的本地作用域,赋值的变量名除非声明为全局变量或非本地变量,否则均为本地变量。在默认的情况下,所有函数定义的内部变量名都位于本地作用域(与函数调用相关的)内。

再来看一个例子来演示一下这两种作用域:
x = 99def func(y): z = x + yreturn zprint(func(1))100这个例子中出现了全局作用域内变量名:x和func
因为x是在模块文件顶层注册的,所以他是全局变量;他能够在函数内部进行引用,仅仅是引用变量不需要进行全局变量声明。
也有本地作用域变量名,y,z
z和参数y都是本地变量,只在函数运行时存在,因为他们都是在函数定义内部进行赋值的,前面我们说过函数的参数也是通过赋值进行传递的。
这种变量名隔离机制存在的意义在于本地变量是作为临时的变量名,只有在函数运行的时候才需要它们,例如,y和z都只存在于函数内部,这些变量名不会与模块命名空间内的变量名(同理,与其他函数内的变量名)产生冲突。


推荐阅读