python中局部变量与全局变量

一、局部变量与全局变量

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)全局与局部变量名一样

python中局部变量与全局变量_第1张图片

说明:因为在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: 多层函数嵌套变量使用

python中局部变量与全局变量_第2张图片

说明:使用了未定义的局部变量,然而num1也不是全局变量,只是count2函数的外层变量,强行使用global定义num1的话同样会报错

C:多层函数嵌套使用global(回答了上面B中为什么强行添加global,也会报错)

python中局部变量与全局变量_第3张图片

说明:在函数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  适用于在局部函数 中 的局部函数, 把最内层的局部 变量设置成外层局部可用,但是:但是还不是全局的,故不能在外部引用该变量

你可能感兴趣的:(python中局部变量与全局变量)