python中变量的作用域LEGB

在 Python 中,变量的作用域决定了变量在程序中的可见性和生命周期。Python 使用 LEGB 规则 来解析变量的作用域,按以下顺序查找变量:

  1. Local(局部作用域)
  2. Enclosing(闭包作用域/外层函数作用域)
  3. Global(全局作用域)
  4. Builtins(内置作用域)

以下是对每个作用域的详细说明:


1. Local(局部作用域)

  • 定义:变量定义在函数或方法内部,仅在该函数内可见。

  • 生命周期:仅在函数执行期间存在,函数退出后销毁。

  • 示例

    def my_function():
        x = 10  # 局部变量
        print(x)
    
    my_function()  # 输出: 10
    print(x)  # 报错: NameError, x 未定义
    
  • 注意

    • 局部变量只能在定义它的函数内访问。
    • 如果在函数内对变量赋值,Python 默认认为它是局部变量,除非显式声明为 nonlocalglobal

2. Enclosing(闭包作用域/外层函数作用域)

  • 定义:在嵌套函数中,内层函数可以访问外层函数的变量(但不能直接修改,除非使用 nonlocal 声明)。

  • 适用场景:主要出现在函数嵌套的情况下,如闭包。

  • 示例

    def outer_function():
        x = 20  # 外层函数变量
        def inner_function():
            print(x)  # 访问外层函数的 x
        inner_function()
    
    outer_function()  # 输出: 20
    
  • 修改 Enclosing 变量
    使用 nonlocal 关键字可以在内层函数中修改外层函数的变量。

    def outer_function():
        x = 20
        def inner_function():
            nonlocal x
            x = 30  # 修改外层 x
        inner_function()
        print(x)
    
    outer_function()  # 输出: 30
    
  • 注意

    • Enclosing 作用域仅在嵌套函数中存在。
    • 如果内层函数没有找到变量,会继续向外查找(Global、Builtins)。

3. Global(全局作用域)

  • 定义:变量定义在模块(文件)级别,对整个模块可见。

  • 生命周期:在模块加载期间存在,直到程序结束。

  • 示例

    x = 100  # 全局变量
    
    def my_function():
        print(x)  # 访问全局变量
    
    my_function()  # 输出: 100
    print(x)  # 输出: 100
    
  • 修改全局变量
    在函数内修改全局变量需要使用 global 关键字。

    x = 100
    def my_function():
        global x
        x = 200  # 修改全局变量
    my_function()
    print(x)  # 输出: 200
    
  • 注意

    • 全局变量可以在模块内的任何函数访问,但直接修改需要 global 声明。
    • 过多使用全局变量可能导致代码难以维护。

4. Builtins(内置作用域)

  • 定义:Python 的内置作用域包含内置函数和对象(如 printlenint 等),在任何地方都可访问。

  • 查找顺序:当变量在 Local、Enclosing 和 Global 作用域中未找到时,Python 会查找 Builtins 作用域。

  • 示例

    def my_function():
        print(len)  # len 是内置作用域中的函数
    
    my_function()  # 输出: <built-in function len>
    
  • 覆盖 Builtins
    可以定义与内置名称相同的变量,但会遮蔽内置作用域中的名称(不推荐)。

    len = 42  # 覆盖内置 len
    print(len)  # 输出: 42
    # print(len("hello"))  # 报错: int 对象不可调用
    
  • 注意

    • 内置作用域是 Python 的最后一道防线,通常不需要显式操作。
    • 避免使用内置名称(如 liststr)作为变量名,以免引起混淆。

LEGB 规则总结

Python 解析变量时按照以下顺序查找:

  1. Local:当前函数或块内的变量。
  2. Enclosing:外层函数的变量(如果有嵌套)。
  3. Global:模块级别的变量。
  4. Builtins:Python 内置的函数和对象。

示例(综合展示 LEGB)

x = "global"

def outer():
    x = "enclosing"
    def inner():
        x = "local"
        print(x)  # 查找 Local: "local"
    inner()
    print(x)  # 查找 Enclosing: "enclosing"

outer()
print(x)  # 查找 Global: "global"
print(len)  # 查找 Builtins: <built-in function len>

输出

local
enclosing
global
<built-in function len>

注意事项

  1. 作用域冲突

    • 如果在函数内对变量赋值,Python 默认将其视为局部变量,除非使用 globalnonlocal 声明。
    • 示例(常见错误):
      x = 10
      def my_function():
          x = x + 1  # 报错: 未定义局部变量 x
          print(x)
      my_function()
      
      修复:使用 global
      x = 10
      def my_function():
          global x
          x = x + 1
          print(x)
      my_function()  # 输出: 11
      
  2. 查找性能

    • LEGB 规则的查找顺序意味着局部变量访问最快,内置作用域最慢(但影响微乎其微)。
  3. 调试技巧

    • 使用 locals() 查看当前局部作用域的变量。
    • 使用 globals() 查看全局作用域的变量。
    • 使用 dir(__builtins__) 查看内置作用域的内容。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MonkeyKing.sun

对你有帮助的话,可以打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值