python函数调用中全局变量与局部变量的分析与理解

此内容来自于沙行勉的《计算机科学导论-以python为舟》

  • 函数调用的基本概念:程序语言中的函数与高中数学中的函数相似。高中函数,假设要实现z+x*y²这个计算。对于乘法计算,定义一个函数f(x,y)=x*y²,他有两个参数x和y。计算x²+y²后得到一个值,作为函数的返回值,赋给f(x,y)。这样就可以用z+f(x,y)来表示上面的运算,对于f(x,y)运算,将会调用到已经定义的函数f(x,y)=x*y²。程序语言中的函数也有参数和返回值,以及定义与调用。程序中的函数就是将一些程序语句结合在一起的部件,可以多次的调用。
  • 函数中的变量:

局部变量:函数中的局部变量只能被这个函数访问,不能被其他函数访问。

全局变量:在函数之外被赋值的变量。

a = 10
def fun():
    a = 20
    print(a)    #函数内a内局部变量
fun()
print(a)        #函数外a为全局变量复制代码

  • 局部变量的判断:
  1. 不出现在global语句中 (global语句为申明某个变量为局部变量)
  2. 出现在函数参数中
  3. 出现在函数参数语句中的等号左边

  • python函数调用:

python进行函数调用时,参数的传递都是通过赋值的方式。

def func(L1):       #定义一个func()函数,参数为L1
    L1.append(1)    #对L1采用.append()方法,结果为[2,1],并且改变全局变量L的值(因为L1和L都指向同一个heap)
L = [2]             
func(L)             #func()函数运行,参数为L,进行赋值传递给func()函数中的局部变量L,
print(L)            func()函数执行完后,局部变量L1指向全局上的值[2,1],L也指向这个全局上的值[2,1](L1与L指向同一块内存区域)复制代码

其中列表做参数时,传递的是指针,函数中的参数指向的内容为全局变量区域,成为heap。

stack-栈,heap-堆

注意事项:

  1. 列表的append、pop、remove等方法,以及给L[i]赋值,对L[i]使用增强赋值等,都会修改列表L所指向的内容,进而对全局产生影响。
  2. 列表的一般合并,或者使用列表的分片(即L[i:j]这种形式)都不会对全局的列表L产生影响。合并与分片的操作会产生新的列表,赋值到一块新的内存区域(heap)上。

  • return(L)返回L的指针:

def F1():
    L = [3,2,1,]    #L是局部变量,而[3,2,1]是在栈的外面heap上。
    return(L)
L = f1() 
print("L=",L)复制代码

全局变量L调用f1()函数,f1()函数中的局部变量L经return返回到函数外的全局变量L,此时局部变量L和全局变量L都指向同一个heap。

  • L做函数参数传递:

def F2():                  #参数L是个指针,是存放在栈上的局部变量
    L = [2,1]              #此语句将函数L又赋值为[2,1]
    return(L)              #return(L)将局部变量L的值赋值给了主调函数的全局变量(例如L = F2(),L是主调函数,F2()则是被调函数)
def F3():               
    L.append(1)            #L指向的是原来的全局内容,会改变全局L
    L[0] = 0
L = [3,2,1]               
L = F2(L);print("L=",L)   
F3(L);print("L=",L)         #调用F3(L)后,L的全局已经被改变复制代码

  • 好的编程习惯:
  1. 尽量避免在函数中使用全局变量
  2. 若在函数中需要使用外部的变量,使用参数传递。
  3. 对函数调用中mutable变量(列表、字典等)



转载于:https://juejin.im/post/5bd58d266fb9a05cf03a305c

你可能感兴趣的:(python)