【Python-Day 20】揭秘Python变量作用域:LEGB规则与global/nonlocal关键字详解

news2025/6/1 19:43:13

Langchain系列文章目录

01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【万字长文】MCP深度解析:打通AI与世界的“USB-C”,模型上下文协议原理、实践与未来

Python系列文章目录

PyTorch系列文章目录

机器学习系列文章目录

深度学习系列文章目录

Java系列文章目录

JavaScript系列文章目录

Python系列文章目录

01-【Python-Day 1】告别编程恐惧:轻松掌握 Python 安装与第一个程序的 6 个步骤
02-【Python-Day 2】掌握Python基石:变量、内存、标识符及int/float/bool数据类型
03-【Python-Day 3】玩转文本:字符串(String)基础操作详解 (上)
04-【Python-Day 4】玩转文本:Python 字符串常用方法深度解析 (下篇)
05-【Python-Day 5】Python 格式化输出实战:%、format()、f-string 对比与最佳实践
06- 【Python-Day 6】从零精通 Python 运算符(上):算术、赋值与比较运算全解析
07-【Python-Day 7】从零精通 Python 运算符(下):逻辑、成员、身份运算与优先级规则全解析
08-【Python-Day 8】从入门到精通:Python 条件判断 if-elif-else 语句全解析
09-【Python-Day 9】掌握循环利器:for 循环遍历序列与可迭代对象详解
10-【Python-Day 10】Python 循环控制流:while 循环详解与 for 循环对比
11-【Python-Day 11】列表入门:Python 中最灵活的数据容器 (创建、索引、切片)
12-【Python-Day 12】Python列表进阶:玩转添加、删除、排序与列表推导式
13-【Python-Day 13】Python 元组 (Tuple) 详解:从创建、操作到高级应用场景一网打尽
14-【Python-Day 14】玩转Python字典(上篇):从零开始学习创建、访问与操作
15-【Python-Day 15】深入探索 Python 字典 (下):常用方法、遍历、推导式与嵌套实战
16-【Python-Day 16】代码复用基石:详解 Python 函数的定义与调用
17-【Python-Day 17】玩转函数参数(上):轻松掌握位置、关键字和默认值
18-【Python-Day 18】玩转函数参数(下):*args 与 **kwargs 终极指南
19-【Python-Day 19】函数的回响:深入理解 return 语句与返回值
20-【Python-Day 20】揭秘Python变量作用域:LEGB规则与global/nonlocal关键字详解


文章目录

  • Langchain系列文章目录
  • Python系列文章目录
  • PyTorch系列文章目录
  • 机器学习系列文章目录
  • 深度学习系列文章目录
  • Java系列文章目录
  • JavaScript系列文章目录
  • Python系列文章目录
  • 前言
  • 一、什么是变量作用域?
    • 1.1 作用域的定义与意义
      • 1.1.1 定义:变量的可见与可访问范围
      • 1.1.2 意义:避免命名冲突、提高代码模块化和可读性
    • 1.2 为什么需要理解作用域?
      • 1.2.1 避免潜在的 Bug
      • 1.2.2 写出更健壮、更易维护的代码
  • 二、Python 的 LEGB 规则详解
    • 2.1 L - Local (局部作用域)
      • 2.1.1 定义与示例
      • 2.1.2 局部变量的生命周期
    • 2.2 E - Enclosing function locals (嵌套函数作用域/闭包作用域)
      • 2.2.1 定义与示例
      • 2.2.2 闭包的概念简介
    • 2.3 G - Global (全局作用域)
      • 2.3.1 定义与示例
      • 2.3.2 全局变量的特点
    • 2.4 B - Built-in (内置作用域)
      • 2.4.1 定义与示例 (如 `len()`, `print()`)
      • 2.4.2 内置作用域的普遍可用性
    • 2.5 LEGB 查找顺序
      • 2.5.1 由内向外的查找规则
  • 三、改变作用域:`global` 与 `nonlocal` 关键字
    • 3.1 `global` 关键字:在函数内部修改全局变量
      • 3.1.1 为什么需要 `global`?
      • 3.1.2 `global` 的使用方法与示例
      • 3.1.3 注意事项与常见误区
    • 3.2 `nonlocal` 关键字:在嵌套函数中修改外层非全局变量
      • 3.2.1 为什么需要 `nonlocal`? (与 `global` 的区别)
      • 3.2.2 `nonlocal` 的使用方法与示例
      • 3.2.3 注意事项与适用场景
  • 四、作用域应用的实际场景与最佳实践
    • 4.1 场景一:模块化编程中的变量隔离
      • 4.1.1 局部变量的优势
    • 4.2 场景二:闭包的应用 (如计数器、状态保持)
      • 4.2.1 使用嵌套作用域的巧妙之处
    • 4.3 场景三:配置管理中的全局变量
      • 4.3.1 合理使用全局变量
    • 4.4 避免作用域相关的常见问题
      • 4.4.1 局部变量覆盖全局变量 (UnboundLocalError)
      • 4.4.2 滥用 `global` 和 `nonlocal`
  • 五、总结


前言

在编程的世界里,变量是我们存储和操作数据的基本单元。然而,一个变量并非在代码的任何位置都可以被随意访问。它们有着自己的“势力范围”,这就是我们今天要探讨的主题——变量作用域(Variable Scope)。理解变量作用域对于编写出逻辑清晰、可维护性高且不易出错的 Python 代码至关重要。

Python 解释器在查找变量时,遵循一套特定的规则,这套规则被称为 LEGB 规则。本篇文章将带您深入剖析 LEGB 规则的每一个层面,并详细讲解如何在需要时使用 globalnonlocal 关键字来“跨越”作用域的界限。无论您是 Python 初学者还是有一定经验的开发者,相信本文都能帮助您更透彻地理解 Python 变量作用域的奥秘。

一、什么是变量作用域?

在正式学习 LEGB 规则之前,我们首先需要明确什么是变量作用域,以及为什么它如此重要。

1.1 作用域的定义与意义

1.1.1 定义:变量的可见与可访问范围

简单来说,变量作用域定义了一个变量在程序中能够被访问的区域。或者说,它规定了变量名的“可见性”和“生命周期”。在一个特定的作用域内定义的变量,通常只能在该作用域内部及其嵌套的子作用域中被直接访问。

1.1.2 意义:避免命名冲突、提高代码模块化和可读性

理解并正确使用作用域带来了诸多好处:

  • 避免命名冲突:不同作用域中可以使用相同的变量名而不会相互干扰。例如,函数内部的局部变量 x 不会影响到全局作用域或其他函数中的同名变量 x
  • 增强代码模块化:函数可以将它们的变量“隐藏”在局部作用域中,只暴露必要的接口,这使得代码更加模块化,降低了不同部分代码之间的耦合度。
  • 提高代码可读性和可维护性:清晰的作用域界限使得代码的逻辑更易于理解和追踪。当出现问题时,可以更快地定位到变量的定义和使用范围。
  • 内存管理:局部变量通常在其作用域执行完毕后就会被销毁,有助于及时释放内存资源。

1.2 为什么需要理解作用域?

1.2.1 避免潜在的 Bug

对作用域理解不清是许多常见错误的根源。例如,试图在变量定义的作用域之外访问它,或者在函数内部无意中修改了全局变量,都可能导致 NameErrorUnboundLocalError 等运行时错误,或者更隐蔽的逻辑错误。

1.2.2 写出更健壮、更易维护的代码

掌握作用域规则能让你更自信地组织代码结构,知道何时何地定义变量最为合适,以及如何安全地在不同代码块之间共享数据。这自然会引导你写出更健壮、更易于他人理解和维护的代码。

二、Python 的 LEGB 规则详解

Python 解释器在查找一个变量时,会按照特定的顺序搜索不同的作用域。这个搜索顺序就是著名的 LEGB 规则,它是以下四个作用域的缩写:

  • Local (局部作用域)
  • Enclosing function locals (嵌套函数作用域/闭包作用域)
  • Global (全局作用域)
  • Built-in (内置作用域)

解释器会从内到外,即按照 L -> E -> G -> B 的顺序查找变量。一旦找到,便停止搜索。如果遍历完所有作用域都未找到该变量,则会抛出 NameError 异常。

2.1 L - Local (局部作用域)

2.1.1 定义与示例

局部作用域(Local Scope)是指在函数内部定义的变量所处的作用域。这些变量通常被称为局部变量。它们只在函数被调用时创建,在函数执行完毕后销毁。

def my_function():
    x = 10  # x 是一个局部变量
    print(f"函数内部: x = {x}")

my_function()
# print(x) # 这行会报错 NameError: name 'x' is not defined,因为 x 在函数外部不可见

在上面的例子中,变量 x 是在 my_function 函数内部定义的,因此它是一个局部变量。它只能在 my_function 函数内部被访问。当函数执行完毕后,x 的生命周期也就结束了。

2.1.2 局部变量的生命周期

  • 创建:当函数被调用,且函数内部的变量赋值语句被执行时创建。
  • 访问:只能在其定义的函数内部被访问。
  • 销毁:当函数执行结束返回或抛出未处理的异常时,该函数内的局部变量通常会被销毁,其占用的内存空间会被回收。

2.2 E - Enclosing function locals (嵌套函数作用域/闭包作用域)

2.2.1 定义与示例

嵌套函数作用域(Enclosing function locals Scope),也常被称为闭包作用域,出现在当一个函数嵌套在另一个函数内部时。外层函数(Enclosing function)的局部作用域对于内层嵌套函数(Nested function)来说就是嵌套函数作用域。

内层函数可以访问外层函数的变量,但默认情况下不能直接修改它们(除非使用 nonlocal 关键字,后续会讲到)。

def outer_function():
    y = 20  # y 在 outer_function 的局部作用域,是 inner_function 的嵌套作用域变量
    def inner_function():
        # z = 30 # z 是 inner_function 的局部变量
        print(f"内层函数: y = {y}") # inner_function 可以访问 outer_function 中的 y
    inner_function()
    # print(z) # 这行会报错 NameError,因为 z 是 inner_function 的局部变量

outer_function()

在这个例子中,inner_function 嵌套在 outer_function 内部。变量 youter_function 的局部变量。对于 inner_function 来说,变量 y 就位于其嵌套函数作用域中。因此,inner_function 可以读取 y 的值。

2.2.2 闭包的概念简介

当一个嵌套函数引用了其外部(但非全局)作用域中的变量,并且该嵌套函数被返回或传递到外部作用域之外时,就形成了一个闭包(Closure)。闭包会“记住”其创建时所处的环境,即使外层函数已经执行完毕,闭包仍然可以访问那些被引用的外部变量。

def greeter(name):
    # name 位于嵌套作用域
    def greet():
        print(f"Hello, {name}!") # greet 函数引用了外部的 name 变量
    return greet # 返回 greet 函数对象

say_hello_to_bob = greeter("Bob")
say_hello_to_alice = greeter("Alice")

say_hello_to_bob()   # 输出: Hello, Bob!
say_hello_to_alice() # 输出: Hello, Alice!

即使 greeter("Bob") 执行完毕后,返回的 say_hello_to_bob 函数(即原来的 greet 函数)仍然能够访问到当时传入的 name 值 “Bob”。这是闭包的一个典型应用。

2.3 G - Global (全局作用域)

2.3.1 定义与示例

全局作用域(Global Scope)是指在模块(通常是一个 .py 文件)的顶层定义的变量所处的作用域。这些变量被称为全局变量。它们在整个模块的生命周期内都存在,并且可以在模块内的任何地方(包括所有函数内部)被访问(读取)。

global_var = 100 # global_var 是一个全局变量

def show_global():
    print(f"函数内部访问全局变量: global_var = {global_var}")

def try_modify_global():
    # global_var = 200 # 如果直接这样写,Python会认为你要创建一个新的局部变量 global_var
                      # 如果之前没有 global_var += 1 这样的操作,而直接赋值,会创建局部变量
                      # 如果之前有读取操作,再赋值,会引发 UnboundLocalError
    print(f"尝试修改前: global_var = {global_var}") # 读取是允许的

show_global()
try_modify_global()
print(f"模块顶层访问全局变量: global_var = {global_var}")

在上述代码中,global_var 在所有函数之外定义,因此它是一个全局变量。show_global 函数可以读取 global_var 的值。然而,在函数内部直接给全局变量赋新值需要特别注意,我们将在 global 关键字部分详细讨论。

2.3.2 全局变量的特点

  • 定义位置:在 Python 文件的顶层,不属于任何函数。
  • 可见性:在整个模块中都可见,包括模块内的所有函数。
  • 生命周期:从被定义开始,直到程序(模块)执行结束。
  • 修改限制:在函数内部,如果想修改全局变量的值,必须使用 global 关键字显式声明。如果仅是读取,则不需要。

2.4 B - Built-in (内置作用域)

2.4.1 定义与示例 (如 len(), print())

内置作用域(Built-in Scope)是 Python 解释器启动时就自动加载的一个特殊作用域。它包含了所有 Python 的内置函数(如 len(), print(), str(), list(), type() 等)和内置常量(如 True, False, None)以及内置异常类型

这些内置名称在任何 Python 代码中都可以直接使用,无需导入或特别声明。

# 这些都是内置作用域的名称
print(len("hello"))       # print 和 len 都是内置函数
print(True)               # True 是内置常量
# my_variable = abs(-5)   # abs 也是内置函数

2.4.2 内置作用域的普遍可用性

内置作用域是 LEGB 规则中查找的最后一层。这意味着,如果你定义了一个与内置名称相同的局部变量或全局变量,那么在该作用域内,你自定义的变量会**覆盖(shadow)**内置名称。

# 不推荐这样做,但可以演示覆盖效果
# str = "这是一个自定义的str变量" # 全局变量 str 覆盖了内置的 str() 类型转换函数
# print(str(123)) # TypeError: 'str' object is not callable

# 恢复内置 str 函数 (通常重启解释器或删除自定义变量)
# del str

def my_func():
    len = lambda x: "Haha, I am a fake len!" # 局部 len 覆盖了内置 len()
    print(len("test"))

my_func() # 输出: Haha, I am a fake len!
print(len("real test")) # 输出: 9 (函数外部的 len 仍然是内置的)

因此,通常建议避免使用与内置名称相同的自定义变量名,以防止混淆和潜在的错误。

2.5 LEGB 查找顺序

2.5.1 由内向外的查找规则

当 Python 代码中引用一个变量名时,解释器会严格按照 L -> E -> G -> B 的顺序去查找这个名称:

  1. L (Local): 首先在当前函数(或代码块)的局部作用域中查找。如果找到,停止搜索并使用该变量。
  2. E (Enclosing function locals): 如果在局部作用域中没有找到,并且当前函数嵌套在其他函数中,则在外层函数的局部作用域中查找。这个查找会逐层向上进行,直到最外层的非全局函数。如果找到,停止搜索。
  3. G (Global): 如果在所有嵌套作用域中都未找到,则在模块级别的全局作用域中查找。如果找到,停止搜索。
  4. B (Built-in): 如果全局作用域中也未找到,则最后在内置作用域中查找。如果找到,停止搜索。
  5. NameError: 如果遍历完所有 LEGB 作用域后仍然没有找到该名称,Python 解释器会引发 NameError 异常。

三、改变作用域:globalnonlocal 关键字

在某些情况下,我们可能需要在函数内部修改定义在外部作用域的变量。Python 提供了两个关键字来实现这一目标:globalnonlocal

3.1 global 关键字:在函数内部修改全局变量

3.1.1 为什么需要 global

默认情况下,如果在函数内部对一个变量进行赋值操作,Python 会认为你正在创建一个新的局部变量,即使在全局作用域中已经存在一个同名变量。如果此时你试图在赋值之前读取该变量(例如 x = x + 1),Python 会因为找不到已定义的局部变量 x 而抛出 UnboundLocalError

如果你确实希望在函数内部修改全局变量的值,而不是创建一个同名的局部变量,就需要使用 global 关键字。

3.1.2 global 的使用方法与示例

global 关键字用于在函数内部声明一个或多个变量是全局变量。声明之后,对这些变量的赋值操作就会直接修改全局作用域中的对应变量。

count = 0  # 全局变量

def increment_global_counter():
    global count  # 声明 count 是全局变量
    count += 1    # 现在修改的是全局 count
    print(f"函数内部: count = {count}")

print(f"调用前: count = {count}") # 输出: 调用前: count = 0
increment_global_counter()      # 输出: 函数内部: count = 1
print(f"调用后: count = {count}") # 输出: 调用后: count = 1

increment_global_counter 函数中,通过 global count 声明,后续的 count += 1 操作修改的是全局变量 count

3.1.3 注意事项与常见误区

  • 声明位置global 声明必须在对该变量进行任何赋值或修改操作之前。通常放在函数体的开头。
  • 仅用于修改:如果只是读取全局变量的值,不需要使用 global 关键字。
    version = "1.0"
    def get_version():
        # global version # 读取时不需要 global
        return version
    print(get_version()) # 输出: 1.0
    
  • 多个变量:可以在一个 global 语句中声明多个全局变量,用逗号隔开:global x, y, z
  • 避免滥用:过度使用全局变量会降低代码的模块化程度和可读性,使得程序状态难以追踪。应尽量通过函数参数和返回值来传递数据,而不是依赖全局变量。

3.2 nonlocal 关键字:在嵌套函数中修改外层非全局变量

3.2.1 为什么需要 nonlocal? (与 global 的区别)

nonlocal 关键字用于在嵌套函数(内部函数)中修改其直接外层函数(Enclosing function)中定义的变量,但这个外层变量不能是全局变量

  • global 用于函数内部修改模块级别的全局变量。
  • nonlocal 用于嵌套函数内部修改其直接外层函数的局部变量(即E层作用域的变量)。

如果没有 nonlocal,在内层函数中对与外层函数同名的变量进行赋值,同样会被视为创建了一个新的内层函数的局部变量。

3.2.2 nonlocal 的使用方法与示例

nonlocal 声明一个或多个变量是来自最近的封闭作用域(不包括全局作用域)的变量。

def outer_func():
    x = 10 # x 是 outer_func 的局部变量,是 inner_func 的嵌套作用域变量

    def inner_func():
        nonlocal x  # 声明 x 是来自外层函数 outer_func 的变量
        x += 5      # 修改的是 outer_func 中的 x
        print(f"内层函数: x = {x}")

    print(f"调用内层函数前: x = {x}") # 输出: 调用内层函数前: x = 10
    inner_func()                     # 输出: 内层函数: x = 15
    print(f"调用内层函数后: x = {x}") # 输出: 调用内层函数后: x = 15

outer_func()

inner_func 中,nonlocal x 使得 x += 5 修改了 outer_func 中的 x

3.2.3 注意事项与适用场景

  • 声明位置:与 global 类似,nonlocal 声明也应在对变量进行赋值或修改之前。
  • 作用域限制nonlocal 只能用于嵌套函数中,并且它引用的变量必须存在于其直接或间接的某个外层函数作用域中,但不能是全局作用域。如果Python在向外查找时,直到全局作用域才找到同名变量,或者根本没找到,都会报错。
  • Python 3 引入nonlocal 是在 Python 3 中引入的关键字。
  • 主要用途:常用于实现闭包中需要修改状态的场景,或者在复杂的嵌套函数结构中管理状态。
def counter_factory():
    count = 0 # 嵌套作用域变量
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

my_counter = counter_factory()
print(my_counter()) # 输出: 1
print(my_counter()) # 输出: 2

在这个闭包实现的计数器中,nonlocal count 确保了每次调用 increment 时,修改的都是 counter_factory 作用域中的那个 count 变量。

四、作用域应用的实际场景与最佳实践

理解了 LEGB 规则以及 globalnonlocal 的用法后,我们来看看它们在实际编程中的应用和一些最佳实践。

4.1 场景一:模块化编程中的变量隔离

4.1.1 局部变量的优势

函数是模块化编程的基本单元。将变量限制在函数的局部作用域内,可以:

  • 减少副作用:函数的操作不会意外修改函数外部的变量。
  • 提高复用性:函数不依赖于外部特定状态(除非通过参数传入),更容易在不同上下文中复用。
  • 简化测试:测试函数时,只需关注其输入和输出,不必担心全局状态的影响。
def process_data(data_list):
    processed_count = 0 # 局部变量,不会影响外部
    result = []
    for item in data_list:
        # ... 一些处理逻辑 ...
        processed_count += 1
        result.append(item * 2) # 假设的处理
    print(f"处理了 {processed_count} 个项目。")
    return result

my_data = [1, 2, 3]
processed_my_data = process_data(my_data)
# processed_count 在这里是不可见的,也不会被 process_data 函数影响

4.2 场景二:闭包的应用 (如计数器、状态保持)

4.2.1 使用嵌套作用域的巧妙之处

闭包利用了嵌套作用域的特性,允许内部函数“记住”并访问其创建时外部环境中的变量,即使外部函数已经执行完毕。这在需要保持状态或创建带有私有数据的函数时非常有用。

前面提到的计数器 counter_factory 就是一个很好的例子。其他应用还包括:

  • 延迟计算:创建一个函数,其行为由创建时的参数决定。
  • 回调函数:创建需要特定上下文信息的回调。
  • 装饰器:装饰器本身就是一种广泛利用闭包和嵌套函数的技术(我们将在后续文章中详细介绍)。

4.3 场景三:配置管理中的全局变量

4.3.1 合理使用全局变量

虽然通常建议限制全局变量的使用,但在某些情况下,它们是合理的,例如:

  • 模块级别的常量:如 PI = 3.14159,或者一些配置参数(如 DEBUG_MODE = True)。这些通常用全大写字母命名,以表示其常量性质。
  • 应用范围的单例对象:例如数据库连接池或日志记录器实例,它们在整个应用程序生命周期中通常只需要一个。

最佳实践

  • 尽量将全局变量定义在模块的顶部。
  • 使用有意义且不易冲突的名称。
  • 对于可配置的全局变量,考虑使用专门的配置模块或配置文件,而不是散布在代码各处。
  • 如果函数需要修改全局变量,务必使用 global 关键字,并清晰注释其原因。

4.4 避免作用域相关的常见问题

4.4.1 局部变量覆盖全局变量 (UnboundLocalError)

当你在函数内部尝试修改一个与全局变量同名的变量,但没有使用 global 声明时,Python 会创建一个新的局部变量。如果在赋值之前就尝试读取它(例如 x = x + 1,其中 x 是全局变量),就会触发 UnboundLocalError: local variable 'x' referenced before assignment

my_global_var = 50

def problematic_function():
    # 错误演示: UnboundLocalError
    # print(my_global_var) # 如果只有这一行,可以正常读取全局变量
    my_global_var = my_global_var + 10 # Python 认为 my_global_var 是局部变量,但右侧读取时它还未赋值
    print(my_global_var)

# problematic_function() # 取消注释会报错

def correct_function():
    global my_global_var
    my_global_var = my_global_var + 10
    print(my_global_var)

correct_function() # 输出: 60

解决方法

  • 如果意图是修改全局变量,使用 global 关键字。
  • 如果意图是使用全局变量的值来计算新的局部变量,确保赋值语句的右侧使用的是明确的全局变量(如果需要),或者将全局变量作为参数传递给函数。

4.4.2 滥用 globalnonlocal

过度使用 globalnonlocal 会使代码的 数据流变得复杂和难以追踪,破坏封装性,增加调试难度。

最佳实践

  • 优先使用参数传递和返回值:这是函数间数据交换最清晰、最推荐的方式。
  • 限制 global 的使用:仅在确实需要在函数内修改全局状态,且没有更好替代方案时使用。通常用于模块级别的配置或状态。
  • 谨慎使用 nonlocalnonlocal 主要用于闭包和较复杂的嵌套函数结构。如果发现嵌套层级过深或 nonlocal 使用频繁,可能需要重新审视函数设计。

五、总结

变量作用域和 LEGB 规则是 Python 编程中非常核心的概念。深刻理解它们有助于我们编写出更高效、更健壮、更易于维护的代码。

在本篇文章中,我们详细探讨了:

  1. 变量作用域的定义与重要性:它决定了变量的可见范围,有助于避免命名冲突,增强代码模块化。
  2. Python 的 LEGB 规则
    • L (Local):函数内部定义的变量。
    • E (Enclosing function locals):嵌套函数中,外层函数的变量。
    • G (Global):模块顶层定义的变量。
    • B (Built-in):Python 解释器预定义的名称。
    • 查找顺序是 L -> E -> G -> B
  3. global 关键字:用于在函数内部声明并修改全局作用域的变量。
  4. nonlocal 关键字:用于在嵌套函数内部声明并修改其直接外层(非全局)函数的变量,常用于闭包。
  5. 作用域的应用场景与最佳实践:包括模块化编程中的变量隔离、闭包的应用、合理使用全局变量以及避免常见的UnboundLocalError和滥用global/nonlocal的问题。

掌握了这些知识,你就能更好地理解 Python 代码中变量是如何被查找和使用的,从而更自信地驾驭 Python 编程。在后续的学习和实践中,请多加留意变量的作用域,这将使你的 Python 之旅更加顺畅!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2393106.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无人机停机坪运行技术分析!

一、运行方式 1. 自动折叠与展开 部分停机坪采用二次折叠设计,通过传动组件实现自动折叠,缩小体积便于运输;展开后最大化停机面积,适应不同任务需求。例如,珠海双捷科技的专利通过两次折叠使停机坪体积最小化&#x…

【Java Web】速通HTML

参考笔记: JavaWeb 速通HTML_java html页面-CSDN博客 目录 一、前言 1.网页组成 1 结构 2 表现 3 行为 2.HTML入门 1 基本介绍 2 基本结构 3. HTML标签 1 基本说明 2 注意事项 4. HTML概念名词解释 二、HTML常用标签汇总 + 案例演示 1. 字体标签 font (1)定义 (2)案例 2…

在线制作幼教早教行业自适应网站教程

你想知道怎么做自适应网站吗?今天就来教你在线用模板做个幼教早教行业的网站哦。 首先得了解啥是自适应网站。简单说呢,自适应网站就是能自动匹配不同终端设备的网站,像手机、平板、电脑等。那如何做幼早教自适应网站呢? 在乔拓云…

Apptrace:APP安全加速解决方案

2021 年,某知名电商平台在 “618” 大促期间遭遇 DDoS 攻击,支付系统瘫痪近 2 小时;2022 年,一款热门手游在新版本上线时因 CC 攻击导致服务器崩溃。观察发现,电商大促、暑期流量高峰和年末结算期等关键商业周期&#…

Web攻防-SQL注入增删改查HTTP头UAXFFRefererCookie无回显报错

知识点: 1、Web攻防-SQL注入-操作方法&增删改查 2、Web攻防-SQL注入-HTTP头&UA&Cookie 3、Web攻防-SQL注入-HTTP头&XFF&Referer 案例说明: 在应用中,存在增删改查数据的操作,其中SQL语句结构不一导致注入语句…

GoldenDB管理节点zk部署

目录 1、准备阶段 1.1、部署规划 1.2、硬件准备 1.3、软件准备 1.4、网络端口开通 1.5、环境清理 2、实施阶段 2.1、操作系统配置 2.1.1、主机名修改 2.1.2、修改hosts文件 2.1.3、禁用防火墙 2.1.4、禁用selinux 2.1.5、禁用透明大页 2.1.6、资源限制调整 2.1.…

mac mini m4命令行管理员密码设置

附上系统版本图 初次使用命令行管理员,让输入密码,无论是输入登录密码还是账号密码,都是错的,百思不得其解,去网上搜说就是登录密码啊 直到后来看到了苹果官方的文档 https://support.apple.com/zh-cn/102367 https…

计算机网络之差错控制中的 CRC(循环冗余校验码)

文章目录 1 概述1.1 简介1.2 特点1.3 基本原则 2 实现步骤3 例题 1 概述 1.1 简介 CRC:Cyclic Redundancy Check(循环冗余校验)是计算机网络中常用的一种差错控制编码方法,用于检测数据传输或存储过程中可能出现的错误。 1.2 特…

【深度学习】7. 深度卷积神经网络架构:从 ILSVRC、LeNet 到 AlexNet、ZFNet、VGGNet,含pytorch代码结构

深度卷积神经网络架构:从 ILSVRC 到 AlexNet 在2012年Alex出现之前,主要还是依赖于SVM,同时数据工程成为分类任务中很大的一个部分,对数据处理的专家依赖性高。 一、ILSVRC 与图像分类任务背景 ILSVRC 简介 ILSVRC&#xff08…

基于cornerstone3D的dicom影像浏览器 第二十七章 设置vr相机,复位视图

文章目录 前言一、VR视图设置相机位置1. 相机位置参数2. 修改mprvr.js3. 调用流程1) 修改Toolbar3D.vue2) 修改View3d.vue3) 修改DisplayerArea3D.vue 二、所有视图复位1.复位流程说明2. 调用流程1) Toolbar3D中添加"复位"按钮,发送reset事件2) View3d.vu…

2025年渗透测试面试题总结-匿名[校招]高级安全工程师(代码审计安全评估)(题目+回答)

安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。、 目录 匿名[校招]高级安全工程师(代码审计安全评估) 渗透基础 1. 自我介绍 2. SQL注入写Shell(分数…

Jenkins实践(7):Publish over SSH功能

在 Jenkins 中使用Publish over SSH功能,需要安装对应的插件。以下是详细步骤: 1. 安装 Publish over SSH 插件 进入 Jenkins 管理界面 → Manage Jenkins → Manage Plugins。切换到 Available 选项卡,搜索 "Publish Over SSH"。勾选插件并点击 Install without…

SQLite 中文写入失败问题总结

SQLite 中文写入失败问题总结与解决方案 在 Windows 下使用 C 操作 SQLite 数据库时,中文字段经常出现 写入成功但内容显示为 BLOB 或 乱码 的问题。根本原因在于 SQLite 要求字符串以 UTF-8 编码 存储,而默认的 std::string 中文通常是 GB2312/ANSI 编…

ubuntu系统安装Pyside6报错解决

目录 1,问题: 2,解决方法: 2.1 首先查看pypi是否有你需要包的镜像: 2.2 其它方案: 2.3 如果下载很慢,可以换源: 2.4 查看系统架构 Windows Ubuntu 1,问题&#xf…

榕壹云医疗服务系统:基于ThinkPHP+MySQL+UniApp的多门店医疗预约小程序解决方案

在数字化浪潮下,传统医疗服务行业正面临效率提升与客户体验优化的双重挑战。针对口腔、美容、诊所、中医馆、专科医院及康复护理等需要预约或诊断服务的行业,我们开发了一款基于ThinkPHP+MySQL+UniApp的多门店服务预约小程序——榕壹云医疗服务系统。该系统通过模块化设计与开…

苏州SAP代理公司排名:工业园区企业推荐的服务商

目录 一、SAP实施商选择标准体系 1、行业经验维度 2、实施方法论维度 3、资质认证维度 4、团队实力维度 二、SAP苏州实施商工博科技 1、SAP双重认证,高等院校支持 2、以SAP ERP为核心,助力企业数字化转型 三、苏州使用SAP的企业 苏州是中国工业…

数据结构中无向图的邻接矩阵详解

在计算机科学的浩瀚宇宙中,数据结构无疑是那把开启高效编程大门的关键钥匙。对于计算机专业的大学生们来说,数据结构课程是专业学习路上的一座重要里程碑,而其中的图结构更是充满魅力与挑战,像一幅神秘的画卷等待我们去展开。今天…

.NET 7 AOT 使用及 .NET 与 Go 语言互操作详解

.NET 7 AOT 使用及 .NET 与 Go 语言互操作详解 目录 .NET 7 AOT 使用及 .NET 与 Go 语言互操作详解 一、背景与技术概述 1.1 AOT 编译技术简介 1.2 Go 语言与 .NET 的互补性 二、.NET 7 AOT 编译实践 2.1 环境准备 2.2 创建 AOT 项目 2.3 AOT 编译流程 2.4 调试信息处…

OpenCV 第7课 图像处理之平滑(一)

1. 图像噪声 在采集、处理和传输过程中,数字图像可能会受到不同噪声的干扰,从而导致图像质量降低、图像变得模糊、图像特征被淹没,而图像平滑处理就是通过除去噪声来达到图像增强的目的。常见的图像噪声有椒盐噪声、高斯噪声等。 1.1 椒盐噪声 椒盐噪声(Salt-and-pepper N…

React 编译器

🤖 作者简介:水煮白菜王,一位前端劝退师 👻 👀 文章专栏: 前端专栏 ,记录一下平时在博客写作中,总结出的一些开发技巧和知识归纳总结✍。 感谢支持💕💕&#…