1、变量的作用域1含义指程序代码能够访问该变量的区域也就是变量生效的范围。Python 中主要有四种作用域局部作用域 (Local)-函数内部嵌套作用域 (Enclosing)-外部函数中全局作用域 (Global)-模块级别内置作用域 (Built-in)-Python 内置的名称2作用域冲突与优先级当不同作用域中存在同名变量时Python 按照 LEGB 规则确定优先级局部变量优先于外部函数变量外部函数变量优先于全局变量全局变量优先于内置名称2、变量的分类根据变量作用域的不同我们可以将变量主要分为两大类局部变量和全局变量。2.1局部变量在Python中局部变量是在函数内部定义的变量。这些变量仅在定义它们的函数内部可见和可用。一旦退出该函数它们就超出了作用域变得不可访问。# 定义函数def func():x局部变量print(func: ,x)# 调用函数func() # func: 局部变量print(外部 ,x) # NameError: name x is not defined2.2 全局变量在Python中全局变量是在函数外部定义的变量。这些变量在程序的整个执行过程中都是可访问的.。x全局变量def func():print(func: ,x)# 调用函数func() # func: 全局变量print(外部: ,x) # 外部: 全局变量注意在Python中如果全局变量和局部变量命名相同那么局部变量会覆盖同名的全局变量在局部作用域内只有局部变量的值会被访问到。但是在全局作用域或其他不包含该局部变量的作用域中全局变量的值仍然保持不变。x全局变量# 定义函数def func():x局部变量 # 定义一个与全局变量同名的局部变量print(func内 ,x)# 调用函数func() # func内 局部变量print(外部 ,x) # 外部 全局变量3、globalnonlocal关键字在Python中global关键字用于在函数内部声明全局变量。允许我们在函数内部修改全局变量。nonlocal关键字用于在内层函数中引用并可能修改外层函数作用域中的局部变量同时确保这个变量不是在当前函数内部新创建的局部变量也不是全局变量。# 定义全局变量count0# 定义函数def counter():global count # 声明count是全局变量count1 # 修改全局变量的值# 调用函数counter()print(外部 ,count) # 外部 1# 定义函数def counter():global count # 声明 count 是全局变量count10# 调用函数counter()print(外部 ,count) # 外部 10思考如果需要声明多个全局变量怎么办如果需要声明多个全局变量在Python中只需在函数内部为每个全局变量使用globa1关键字即可。global关键字后面可以跟随一个或多个由逗号分隔的变量名。#定义函数def func():global var1, var2, var3var1 10var2 Hellovar3 [1, 2, 3]#在调用函数之前这些变量在全局作用域中不存在#调用函数func()print(var1: ,var1) # var1: 10print(var2: ,var2) # var2: Helloprint(var3: ,var3) # var3: [1, 2, 3]使用 nonlocal 的注意事项nonlocal只能引用外部函数的变量不能引用全局变量被引用的变量必须存在于某个外部函数的作用域中nonlocal声明必须在变量使用前出现4、嵌套函数 (Nested Functions)嵌套函数是在另一个函数内部定义的函数。在 Python 中嵌套函数可以访问其外部函数中定义的变量。# 定义函数def outer(): # 外层函数a10 # 外层函数的局部变量print(outer1: , a) # outer1: 10def inner(): # 内层函数nonlocal a # 声明a是外层函数的局部变量a20 # 修改外层函数的局部变量print(inner: , a) # inner: 20inner()print(outer2: , a) # outer2: 20# 调用函数outer() # 调用外层函数嵌套函数的特点内部函数可以读取外部函数中定义的变量默认情况下内部函数不能修改外部函数中定义的变量创建同名局部变量可以使用nonlocal关键字允许内部函数修改外部函数中定义的变量5、闭包什么是闭包Closure一个内部函数引用了它外部函数的局部变量即使外部函数已经执行完毕这个内部函数依然“记得”它外部的变量。闭包的结构特征三个条件1函数嵌套函数里面定义函数2内部函数使用了外部函数的局部变量3外部函数返回内部函数经典闭包示例def outer():msg 我是外部变量def inner():print(f内部访问{msg}) # 引用了外层局部变量return inner # 返回内部函数不调用它f outer() # 执行 outer()返回的是 inner 函数对象f() # 实际调用 inner()依然可以访问 msg闭包变量nonlocaldef outer():x 10def inner():nonlocal xx 1print(fx {x})return innerf outer()f() # 输出x 11f() # 输出x 126、总结作用域层级全局作用域 ← global↓函数作用域 ← nonlocal闭包外层↓嵌套函数 ← 闭包内层1避免使用全局变量全局变量使代码难以理解和维护尽量通过参数传递和返回值来共享数据2减少使用 global 和 nonlocal 关键字过度使用会使代码难以追踪和理解考虑使用类来管理状态而不是依赖嵌套函数和变量3避免使用与内置函数同名的变量避免使用 list、dict、sum、max 等作为变量名可以使用类似 list_、dict_ 的命名方式或更具描述性的名称4利用闭包特性嵌套函数可以记住并访问其外部作用域中的变量闭包可以用于创建拥有私有状态的函数闭包嵌套函数 引用外层变量 返回内层函数nonlocal闭包中修改外层函数变量的关键字global函数中修改全局变量的关键字与闭包无关最佳实践闭包 nonlocal替代全局变量更安全关键字 / 概念作用范围用途必须在闭包里吗global全局变量在函数内修改全局变量❌ 无关nonlocal外层函数的局部变量闭包中修改外层变量✅ 专门给闭包用闭包外层函数变量 内层函数封装私有数据、持久化状态—
变量的作用域,global,nonlocal,闭包
1、变量的作用域1含义指程序代码能够访问该变量的区域也就是变量生效的范围。Python 中主要有四种作用域局部作用域 (Local)-函数内部嵌套作用域 (Enclosing)-外部函数中全局作用域 (Global)-模块级别内置作用域 (Built-in)-Python 内置的名称2作用域冲突与优先级当不同作用域中存在同名变量时Python 按照 LEGB 规则确定优先级局部变量优先于外部函数变量外部函数变量优先于全局变量全局变量优先于内置名称2、变量的分类根据变量作用域的不同我们可以将变量主要分为两大类局部变量和全局变量。2.1局部变量在Python中局部变量是在函数内部定义的变量。这些变量仅在定义它们的函数内部可见和可用。一旦退出该函数它们就超出了作用域变得不可访问。# 定义函数def func():x局部变量print(func: ,x)# 调用函数func() # func: 局部变量print(外部 ,x) # NameError: name x is not defined2.2 全局变量在Python中全局变量是在函数外部定义的变量。这些变量在程序的整个执行过程中都是可访问的.。x全局变量def func():print(func: ,x)# 调用函数func() # func: 全局变量print(外部: ,x) # 外部: 全局变量注意在Python中如果全局变量和局部变量命名相同那么局部变量会覆盖同名的全局变量在局部作用域内只有局部变量的值会被访问到。但是在全局作用域或其他不包含该局部变量的作用域中全局变量的值仍然保持不变。x全局变量# 定义函数def func():x局部变量 # 定义一个与全局变量同名的局部变量print(func内 ,x)# 调用函数func() # func内 局部变量print(外部 ,x) # 外部 全局变量3、globalnonlocal关键字在Python中global关键字用于在函数内部声明全局变量。允许我们在函数内部修改全局变量。nonlocal关键字用于在内层函数中引用并可能修改外层函数作用域中的局部变量同时确保这个变量不是在当前函数内部新创建的局部变量也不是全局变量。# 定义全局变量count0# 定义函数def counter():global count # 声明count是全局变量count1 # 修改全局变量的值# 调用函数counter()print(外部 ,count) # 外部 1# 定义函数def counter():global count # 声明 count 是全局变量count10# 调用函数counter()print(外部 ,count) # 外部 10思考如果需要声明多个全局变量怎么办如果需要声明多个全局变量在Python中只需在函数内部为每个全局变量使用globa1关键字即可。global关键字后面可以跟随一个或多个由逗号分隔的变量名。#定义函数def func():global var1, var2, var3var1 10var2 Hellovar3 [1, 2, 3]#在调用函数之前这些变量在全局作用域中不存在#调用函数func()print(var1: ,var1) # var1: 10print(var2: ,var2) # var2: Helloprint(var3: ,var3) # var3: [1, 2, 3]使用 nonlocal 的注意事项nonlocal只能引用外部函数的变量不能引用全局变量被引用的变量必须存在于某个外部函数的作用域中nonlocal声明必须在变量使用前出现4、嵌套函数 (Nested Functions)嵌套函数是在另一个函数内部定义的函数。在 Python 中嵌套函数可以访问其外部函数中定义的变量。# 定义函数def outer(): # 外层函数a10 # 外层函数的局部变量print(outer1: , a) # outer1: 10def inner(): # 内层函数nonlocal a # 声明a是外层函数的局部变量a20 # 修改外层函数的局部变量print(inner: , a) # inner: 20inner()print(outer2: , a) # outer2: 20# 调用函数outer() # 调用外层函数嵌套函数的特点内部函数可以读取外部函数中定义的变量默认情况下内部函数不能修改外部函数中定义的变量创建同名局部变量可以使用nonlocal关键字允许内部函数修改外部函数中定义的变量5、闭包什么是闭包Closure一个内部函数引用了它外部函数的局部变量即使外部函数已经执行完毕这个内部函数依然“记得”它外部的变量。闭包的结构特征三个条件1函数嵌套函数里面定义函数2内部函数使用了外部函数的局部变量3外部函数返回内部函数经典闭包示例def outer():msg 我是外部变量def inner():print(f内部访问{msg}) # 引用了外层局部变量return inner # 返回内部函数不调用它f outer() # 执行 outer()返回的是 inner 函数对象f() # 实际调用 inner()依然可以访问 msg闭包变量nonlocaldef outer():x 10def inner():nonlocal xx 1print(fx {x})return innerf outer()f() # 输出x 11f() # 输出x 126、总结作用域层级全局作用域 ← global↓函数作用域 ← nonlocal闭包外层↓嵌套函数 ← 闭包内层1避免使用全局变量全局变量使代码难以理解和维护尽量通过参数传递和返回值来共享数据2减少使用 global 和 nonlocal 关键字过度使用会使代码难以追踪和理解考虑使用类来管理状态而不是依赖嵌套函数和变量3避免使用与内置函数同名的变量避免使用 list、dict、sum、max 等作为变量名可以使用类似 list_、dict_ 的命名方式或更具描述性的名称4利用闭包特性嵌套函数可以记住并访问其外部作用域中的变量闭包可以用于创建拥有私有状态的函数闭包嵌套函数 引用外层变量 返回内层函数nonlocal闭包中修改外层函数变量的关键字global函数中修改全局变量的关键字与闭包无关最佳实践闭包 nonlocal替代全局变量更安全关键字 / 概念作用范围用途必须在闭包里吗global全局变量在函数内修改全局变量❌ 无关nonlocal外层函数的局部变量闭包中修改外层变量✅ 专门给闭包用闭包外层函数变量 内层函数封装私有数据、持久化状态—