一、局部变量与全局变量
python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量
(1)局部变量外部访问
def change_name():
name = '局部变量'
print('函数内部修改name值为:', name)
change_name()
print('函数外部打印name的值为:', name)
"""
运行结果:
函数内部修改name值为: 局部变量
print('函数外部打印name的值为:', name)
NameError: name 'name' is not defined
"""
说明:报错可以看出,在外部访问函数内部的局部变量是不可行的,因为局部变量name的作用域只在change_name()中
(2)函数内部访问全局变量且修改全局变量
def change_name(name):
print('函数内部修改name值之前为:', name)
name = '局部变量'
print('函数内部修改name值为:', name)
change_name(name)
print('函数外部打印name的值为:', name)
"""
运行结果:
函数内部修改name值之前为: 全局变量
函数内部修改name值为: 局部变量
函数外部打印name的值为: 全局变量
"""
说明:可以看到在函数内部对全局变量的修改后,在函数执行完毕,修改的结果是无效的,全局变量并不会受到影响
????????老夫不能接受这个肤浅的解释,那我们打印出变量的内存地址试试
def change_name(name):
print('函数内部修改name值之前为的内存地址为:', id(name))
name = '局部变量'
print('函数内部修改name值之后的内存地址为:',id(name))
change_name(name)
print('函数外部打印name的内存地址值为:', id(name))
"""
运行结果:
函数内部修改name值之前为的内存地址为: 2147662653208
函数内部修改name值之后的内存地址为: 2147663637912
函数外部打印name的内存地址值为: 2147662653208
"""
说明:任性的我这下明白了,在函数内部修改之后,会在内存中重新开辟一块内存地址,与之前外面的全局变量的地址不搭嘎啊,所以不会影响全局变量的值
(3)全局与局部变量名一样
说明:因为在change_name()函数使用了局部变量name,它只是个跟全局变量同名的局部变量,使用前还是要赋值,不赋值就使用就是不合法,再或者说:如果内部函数有引用外部函数的同名变量或者全局变量,并且对这个变量有修改.那么python会认为它是一个局部变量,又因为函数中没有name的定义和赋值,所以报错,但是如果你不修改,那么不会报错
二:全局/局部变量中的复杂数据类型
name = [1, 2, 3, 4]
def change_name():
print('函数内部打印name[0]的内存地址:', id(name[0]))
name[0] = name[0] + 1
print('函数内部打印name[0]的内存地址:', id(name[0]))
print('函数内部打印name[0]的值:', name[0])
change_name()
print('函数外部打印name[0]的内存地址:', id(name[0]))
print('函数外部打印name[0]的值:', name[0])
"""
运行结果:
函数内部打印name[0]的内存地址: 140719482123088
函数内部打印name[0]的内存地址: 140719482123120
函数内部打印name[0]的值: 2
函数外部打印name[0]的内存地址: 140719482123120
函数外部打印name[0]的值: 2
"""
说明:可以看出这里在函数内部修改全局变量可以,并且修改之后,全局变量的值也改变了,根据运行结果可以看出,其实操作的都是同一块内存地址的值,特别说明:复杂的数据类型;如列表,字典,集合,类,都可以函数内部修改
三、关键字global与nonlocal的使用
特别说明:千万不要在函数内部强制性修改全局变量本身的值,你不知道有多少个地方引用这个全局变量,万一出了问题,调试到你想死
(1)A:在函数里面修改全局变量本身
name = '全局变量'
def change_name(n):
global name
name = n
print('函数内部打印name的值:', name)
print('函数内部打印name的内存地址值:', id(name))
change_name('global')
print('函数外部打印name的值:', name)
print('函数外部打印name的内存地址:', id(name))
"""
运行结果:
函数内部打印name的值: global
函数内部打印name的内存地址值: 2170632629640
函数外部打印name的值: global
函数外部打印name的内存地址: 2170632629640
"""
说明:可以看书这里修改是同一块内存地址的变量值,使用global关键字就是告诉python编译器这个变量不是局部变量而是全局变量,其实有点像是"引用"的意思
B: 多层函数嵌套变量使用
说明:使用了未定义的局部变量,然而num1也不是全局变量,只是count2函数的外层变量,强行使用global定义num1的话同样会报错
C:多层函数嵌套使用global(回答了上面B中为什么强行添加global,也会报错)
说明:在函数count2内 global 定义的变量 num1,只能在 函数 count2内引用, 如果要在 add_one内修改,必须在 add_one 函数里面声明 再global num1 ,表明是修改外面的 全局变量 num1.相当于你声明了,才能引用修改(2)
(3)nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量
def count2(n):
num1=n
print('外层变量num1的内存地址:',id(num1))
def add_one():
nonlocal num1
print('内层变量num1的内存地址:', id(num1))
num1 += 1
return num1
return add_one()
num3 = count2(4)
"""
运行结果:
外层变量num1的内存地址: 140719532454832
内层变量num1的内存地址: 140719532454832
"""
说明: nonlocal 适用于在局部函数 中 的局部函数, 把最内层的局部 变量设置成外层局部可用,但是:但是还不是全局的,故不能在外部引用该变量