当前位置:首页>python>从零开始学python-作用域

从零开始学python-作用域

  • 2026-09-04 19:09:32
从零开始学python-作用域

Hi~新朋友,记得点上面蓝字(网虫root)关注哟~

前言:

作用域(Scope)是指变量在程序中的可见范围和生命周期。简单来说,它决定了在代码的哪些部分可以访问某个变量。理解作用域对于编写正确、可维护的代码至关重要,尤其是在函数和模块中。

Python使用LEGB规则来查找变量,即按照局部(Local)→ 嵌套(Enclosing)→ 全局(Global)→ 内置(Built-in)的顺序进行搜索。

一. 局部作用域(Local)

局部作用域是指在函数内部定义的变量所在的作用域。这些变量只能在函数内部访问,函数执行结束后会被销毁。

def my_func():    x = 10          # x 是局部变量    print(x)my_func()           # 输出: 10# print(x)          # 报错: NameError: name 'x' is not defined

二. 嵌套作用域(Enclosing)

嵌套作用域出现在函数嵌套(函数内部定义另一个函数)的情况下。外层函数的变量对内层函数来说是“嵌套作用域”中的变量,内层函数可以访问这些变量,但不能修改(除非使用 nonlocal 关键字)。

def outer():    y = 20          # 外层变量    def inner():        print(y)    # 内层函数可以访问外层变量    inner()outer()             # 输出: 20

三. 全局作用域(Global)

全局作用域是指在模块(文件)顶层定义的变量所在的作用域(不在任何函数内)。全局变量可以在整个模块中访问,但在函数内部修改全局变量需要使用 global 关键字。

z = 30              # 全局变量def show():    print(z)        # 可以访问全局变量def modify():    global z    z = 40          # 修改全局变量show()              # 输出: 30modify()show()              # 输出: 40

四. 内置作用域(Built-in)

内置作用域包含了Python预定义的名称,如 print、len、range 等。这些名称在程序的任何地方都可以直接使用。

print(len([1, 2, 3]))   # 输出: 3,len 来自内置作用域

五. LEGB规则详解

当在函数内部引用一个变量时,Python解释器会按照以下顺序查找:

  • Local:首先在当前函数(或lambda)的局部作用域中查找变量。

  • Enclosing:如果没找到,则向外层嵌套函数的作用域查找(如果有嵌套的话)。

  • Global:如果还没找到,则到全局作用域(当前模块)查找。

  • Built-in:最后在内置作用域中查找。

如果所有作用域中都找不到该变量,就会抛出 NameError。

🌲示例:LEGB查找顺序

# 内置作用域中的名称print("Hello")          # print 是内置函数x = "global x"          # 全局变量def outer():    x = "outer x"       # 外层嵌套变量    def inner():        x = "inner x"   # 局部变量        print(x)        # 输出: inner x (局部)    inner()outer()def outer2():    x = "outer x"    def inner2():        print(x)        # 未定义局部 x,向外层找    inner2()outer2()                # 输出: outer xdef outer3():    def inner3():        print(x)        # 未定义局部,无嵌套,找全局    inner3()outer3()                # 输出: global xdef error_func():    print(unknown_var)  # 在所有作用域中都找不到# error_func()          # 报错: NameError

六. global 和 nonlocal 语句

⏳global 关键字

用于在函数内部声明一个变量是全局变量,从而可以修改它(而不是创建一个新的局部变量)。

counter = 0def increment():    global counter    counter += 1increment()increment()print(counter)          # 输出: 2
  • 如果没有 global,函数内部的 counter += 1 会试图访问一个未定义的局部变量,导致 UnboundLocalError。

  • 使用场景: 函数内修改模块级变量

📚nonlocal 关键字

用于在嵌套函数中声明一个变量来自外层函数(非全局),从而可以修改它。

def outer():    count = 0    def inner():        nonlocal count        count += 1        print(count)    inner()    inner()outer()                 # 输出: 1\n2
  • 如果不使用 nonlocal,内层函数中的 count += 1 也会引发 UnboundLocalError。

  • 使用场景: 嵌套函数中修改外层函数的变量

⏳重要提示:

  • global 仅在函数内使用,不能用于修改内置作用域。
  • nonlocal必须在嵌套函数中使用,且不能作用于全局变量。

七. 常见陷阱与注意事项

1、变量赋值即定义:在函数内部对变量进行赋值(即使是 += 这类操作),默认会将其视为局部变量,除非使用 global 或 nonlocal 声明。

a = 1def test():    print(a)    # 这里会引发 UnboundLocalError,因为后面有 a = 2    a = 2test()        # 报错

这是因为Python在编译函数时,如果发现函数内部有对 a 的赋值,就会将 a 标记为局部变量,导致前面的 print(a) 试图访问一个未定义的局部变量。

2、可变对象的修改:如果不重新赋值,只是修改可变对象的内容(如列表的 append),不需要 global 或 nonlocal。

lst = [1, 2]def add_item():    lst.append(3)    # 修改列表内容,不是重新赋值add_item()print(lst)           # 输出: [1, 2, 3]

3、内置名称的覆盖:避免使用与内置函数相同的变量名,否则会覆盖内置作用域中的名称,导致后续无法使用该内置功能。

len = 10          # 覆盖了内置函数 lenprint(len("abc")) # 报错: 'int' object is not callable

4、未使用global

x = 10def bad_example():    x = 20  # 未声明global → 创建局部变量x,不影响全局xbad_example()print(x)  # 输出: 10 (正确!但非预期结果)

验证:

  • 未用global时,x = 20在函数内创建局部变量,全局x保持为10。

  • 输出结果:10(符合预期,说明错误处理正确)。

5、nonlocal 误用(变量未定义)

def outer():    def inner():        nonlocal x  # 错误!x未在Enclosing作用域中定义        x = 30    inner()outer()  # 运行时抛出: NameError: name 'x' is not defined

验证:

  • nonlocal 要求变量必须在外层函数作用域中存在(如outer中定义x)。

  • 错误类型:NameError

八. 作用域与命名空间

作用域与命名空间密切相关。命名空间是名称到对象的映射,而作用域是命名空间在代码中的可见范围。不同的作用域对应不同的命名空间:

  • 局部命名空间:函数执行时创建,函数返回后销毁。

  • 全局命名空间:模块加载时创建,贯穿程序运行。

  • 内置命名空间:Python解释器启动时创建,一直存在。

可以使用内置函数 locals()、globals() 查看当前局部和全局命名空间的内容。

九. 作用域常见问题总结

问题场景
错误原因
正确做法
函数内修改全局变量失败
未使用global
添加global var_name
嵌套函数修改外层变量失败
未使用nonlocal
添加nonlocal var_name
在模块顶层直接修改global
无需global(已在全局作用域)
直接赋值(如x = 5)
在函数内使用nonlocal修改全局
nonlocal
不能作用于全局变量
改用global

十. 总结

  • Python的作用域遵循LEGB规则:Local → Enclosing → Global → Built-in。

  • 函数内部可以直接读取外层和全局变量,但修改需要使用 global 或 nonlocal。

  • 变量赋值默认在局部作用域中创建新变量。

  • 关键语法:global(全局)和nonlocal(嵌套)是修改作用域变量的唯一安全方式。

最佳实践:

  • 尽量避免全局变量(减少副作用)。

  • 用nonlocal时确保变量在Enclosing作用域中存在。

  • 用global时明确声明,避免意外修改。

【微语】不要害怕失去任何人和事,任何时候都要有从头再来的勇气。

网虫root

期待你的

分享

点赞

在看

最新文章

随机文章