Python基础:变量作用域与嵌套函数

Python基础:变量作用域与嵌套函数



一、知识点详解

1.1 变量作用域

  • 定义:变量在程序中可被访问的区域,分为 全局作用域局部作用域

    作用域类型定义位置访问范围
    全局作用域函数外部定义整个程序
    局部作用域函数内部定义仅在函数内部
  • 示例

    global_var = "全局变量"  # 全局作用域
    
    def test_scope():
        local_var = "局部变量"  # 局部作用域
        print(global_var)      # 可访问全局变量 → "全局变量"
    
    test_scope()
    print(local_var)  # ❌ 报错:NameError(无法访问局部变量)
    

1.2 全局变量与局部变量

  • 1.2.1 访问与修改全局变量
    直接访问:函数内部可直接读取全局变量。
    修改全局变量:需使用 global 关键字声明。

    count = 0  # 全局变量
    
    def increment():
        global count  # 声明使用全局变量
        count += 1
    
    increment()
    print(count)  # 1
    
  • 1.2.2 变量优先级
    当全局变量与局部变量同名时,在函数内部优先使用局部变量。

    x = "全局"
    
    def demo():
        x = "局部"  # 创建同名局部变量
        print(x)   # 输出:局部
    
    demo()
    print(x)       # 输出:全局
    

1.3 嵌套函数

  • 1.3.1 嵌套函数基础
    定义:在函数内部定义另一个函数,形成层级结构。
    基础结构

    def outer():
        print("外部函数")
        def inner():
            print("内部函数")
        inner()  # 在外部函数内调用内部函数
    
    outer()
    # 输出:
    # 外部函数
    # 内部函数
    
  • 1.3.2 访问外层变量
    内部函数可读取外部函数的局部变量(但默认不可修改)。

    def outer():
        outer_var = 10
        def inner():
            print(f"内部访问外部变量:{outer_var}")  # 可读取
        inner()
    
    outer()  # 输出:内部访问外部变量:10
    
  • 1.3.3 修改外层变量
    注意:直接修改外层变量会创建新的局部变量。

    def outer():
        counter = 0
        def inner():
            counter = 1  
            # 此时会创建新的局部变量counter,外层counter不变
            # 若要修改外层counter,需使用nonlocal关键字声明
        inner()
        print(counter)   # 输出:0(未修改)
    
  • 1.3.4 nonlocal关键字
    作用:允许内层函数修改外层函数的局部变量(非全局变量)。
    注意nonlocal只能修改外层函数的局部变量,若外层无对应变量会报SyntaxError

    def outer():
        counter = 0
        def inner():
            nonlocal counter  # 声明修改外层变量
            counter += 1
        inner()
        print(counter)  # 输出:1
    
    outer()
    

1.4 变量作用域规则(LEGB)

  • 定义:Python按 L→E→G→B 顺序查找变量,即:
    1. L(Local) :当前函数内的局部变量
    2. E(Enclosing) :外层嵌套函数的局部变量
    3. G(Global) :全局变量(模块级别)
    4. B(Built-in) :内置函数(如print, len

  • 说明示例

    x = "全局变量"  # G层
    
    def outer():
        x = "外层变量"  # E层
        def inner():
            x = "局部变量"  # L层
            print(x)      # 输出:局部变量
        inner()
    
    outer()
    print(x)  # 输出:全局变量
    

1.5 LEGB规则详解

  • 1. Local(局部作用域)
    函数内部定义的变量(含参数)
    优先级最高,仅在函数内有效

    def func():
        local_var = 10
        print(local_var)  # 10
    
    func()
    print(local_var)  # ❌ 报错:未定义
    
  • 2. Enclosing(嵌套外层作用域)
    外层嵌套函数的局部变量。
    需用nonlocal声明修改。

    def outer():
        outer_var = 10
        def inner():
            nonlocal outer_var  # 声明修改Enclosing层变量
            outer_var += 1
        inner()
        print(outer_var)  # 11
    
    outer()
    
  • 3. Global(全局作用域)
    模块级别定义的变量。
    需用global声明修改。

    global_var = 100
    
    def update_global():
        global global_var
        global_var = 200
    
    update_global()
    print(global_var)  # 200
    
  • 4. Built-in(内置作用域)
    Python预定义的函数和变量。
    当其他层找不到时,最后查找内置层。

    def test_len():
        # len = "局部变量"  # 若取消注释,将覆盖内置len函数, 导致下方语句报错
        print(len([1,2,3]))  # 3
    
    test_len()
    
  • 总结表格

    作用域层定义位置修改方式生命周期
    Local函数内部直接赋值函数执行期间
    Enclosing外层嵌套函数nonlocal声明外层函数执行期间
    Global模块顶层global声明程序运行期间
    Built-inPython内置不可修改解释器启动到关闭

二、说明示例

2.1 多层嵌套函数与LEGB规则应用

# 全局变量,处于G层
global_num = 100

def outer():
    # 外层函数的局部变量,处于E层
    outer_num = 20

    def middle():
        # 中间层函数的局部变量,处于E层(相对内层函数)
        middle_num = 30

        def inner():
            # 内层函数的局部变量,处于L层
            local_num = 40
            # 按照LEGB规则,先查找L层,找到local_num
            print(f"Local层变量: {local_num}")
            # 查找E层,找到middle_num
            print(f"Enclosing层(middle函数)变量: {middle_num}")
            # 查找E层,找到outer_num
            print(f"Enclosing层(outer函数)变量: {outer_num}")
            # 查找G层,找到global_num
            print(f"Global层变量: {global_num}")
            nonlocal middle_num
            middle_num += 1
            return middle_num

        result = inner()
        print(f"修改后的middle_num: {result}")

    middle()

outer()

2.2 使用 globalnonlocal 实现计数器

# 全局计数器
global_count = 0

def create_counter():
    # 局部计数器
    local_count = 0

    def increment():
        nonlocal local_count
        local_count += 1
        global global_count
        global_count += 1
        print(f"局部计数器: {local_count}, 全局计数器: {global_count}")
        return local_count

    return increment

# 创建计数器函数
counter = create_counter()

# 多次调用计数器函数
counter()
counter()
counter()

三、知识点总结

  1. 变量作用域
    全局作用域:函数外定义,全程序可访问;
    局部作用域:函数内定义,仅限函数内访问。

  2. 全局与局部变量
    函数内可直接读取全局变量,修改需用 global 声明;
    存在同名变量时,局部变量优先于全局变量(函数内)。

  3. 嵌套函数
    函数内可定义子函数;
    内部函数可读取外层函数变量,修改需用 nonlocal 声明。

  4. LEGB规则
    Python查找变量顺序:局部(L) → 嵌套外层(E) → 全局(G) → 内置(B)

  5. 相似知识对比

    概念核心规则应用场景
    全局作用域函数外定义,全程序可见全局配置、共享计数器
    局部作用域函数内定义,仅限函数内有效临时计算、内部变量
    global修改全局变量跨函数共享全局数据
    nonlocal修改嵌套外层函数的变量嵌套函数中保留状态

四、扩展知识

4.1 规则验证函数

函数作用返回值类型
locals()获取当前作用域的局部变量字典dict
globals()获取当前作用域的全局变量字典dict

说明示例

# 全局作用域(G层)
global_var = "全局变量"
global_list = [1, 2, 3]

def outer():
    # 外层函数局部作用域(E层)
    outer_var = "外层变量"
    
    def inner():
        # 内层函数局部作用域(L层)
        inner_var = "内层变量"
        
        # 打印当前作用域的局部变量(L层)
        print("\n--- 内层函数 locals() ---")
        print(locals())  # 输出:{'inner_var': '内层变量', ...}
        
        # 访问全局变量(通过 globals())
        globals()["global_var"] = "全局变量(已修改)"  # 修改全局变量
        print("全局变量 global_var:", globals()["global_var"])
    
    inner()
    
    # 打印外层函数的局部变量(E层)
    print("\n--- 外层函数 locals() ---")
    print(locals())  # 输出:{'outer_var': '外层变量', 'inner': <function>}

# 调用外层函数
outer()

# 在全局作用域中打印 globals()
print("\n--- 全局作用域 globals() ---")
print("全局变量 global_list:", globals()["global_list"])

五、知识点考察题

x = 1

def outer():
    x = 2
    def middle():
        x = 3
        def inner():
            nonlocal x
            print(x)
        inner()
    middle()
    print(x)
outer()
print(x)

以上代码三次打印输出分别是什么( )

  • A. 3 3 3
  • B. 3 3 1
  • C. 3 2 1
  • D. 3 2 3

答案:C

解析

  1. 第一次打印在inner()函数中,nonlocal x指向middle()函数中的x=3,故输出3
  2. 第二次打印在outer()函数中,其局部变量x=2未被修改,故输出2
  3. 第三次打印在全局作用域,全局变量x=1未被修改,故输出1



关注「安于欣」获取更多Python技巧


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值