您的位置:首页 > 财经 > 产业 > 深圳seo博客_企点官网下载_视频网站建设_百度关键词优化企业

深圳seo博客_企点官网下载_视频网站建设_百度关键词优化企业

2025/3/18 15:57:37 来源:https://blog.csdn.net/xiaoyuting999/article/details/145945610  浏览:    关键词:深圳seo博客_企点官网下载_视频网站建设_百度关键词优化企业
深圳seo博客_企点官网下载_视频网站建设_百度关键词优化企业

  • 变量作用域
    • 全局作用域(Global scope) 和 内置作用域(Built-in scope)
    • 局部作用域(Local scope)
      • 局部作用域的创建与销毁
      • 函数每次调用都会创建新的局部作用域
    • 变量查找(Variable lookups)
    • `global` 关键字
      • 在函数内修改全局变量
      • 使用 `global` 关键字修改全局变量
    • `nonlocal` 关键字
    • 非局部作用域(Nonlocal scope)
      • 访问封闭作用域的变量
    • `nonlocal` 关键字

变量作用域

参考文章:Python nonlocal、Python Variable Scopes

当你将一个对象赋值给一个变量时,该 变量会在内存中引用该对象。这意味着 变量被绑定到该对象,可以 通过变量名访问该对象,但是要注意 变量名 及其 绑定变量名和对象)仅存在于代码的特定部分。

Python 将这些 绑定 存储在 命名空间(namespace 中。每个作用域都有自己的命名空间

全局作用域(Global scope) 和 内置作用域(Built-in scope)

  • 全局作用域global scope)本质上就是 模块作用域module scope),它仅限于 单个 Python 源代码文件

  • 内置作用域built-in scope)是一个 跨所有模块 的真正全局作用域,它提供全局可用的对象,例如 printlenNoneTrueFalse 等。

  • 在内部,全局作用域是嵌套在内置作用域之中的
    在这里插入图片描述

如果你在某个作用域中 访问一个变量,而 Python 在该作用域的命名空间中找不到 它,它会 继续在外层作用域的命名空间中查找

假设你在一个名为 app.py 的模块中有以下语句:

print('Hello')
  • app.py 模块中,Python 会首先在模块作用域app.py)中查找 print 函数。

  • 由于 Python 在 app.py 的模块作用域中找不到 print 函数的定义,它会向上查找外层作用域,即内置作用域(built-in scope),并在那里寻找 print 函数。

  • 在这种情况下,Python 能够在内置作用域中找到 print 函数并正确执行。
    在这里插入图片描述

局部作用域(Local scope)

当你创建一个函数时,可以在函数内定义参数变量。例如:

def increment(counter, by=1):result = counter + byreturn result

当执行代码时,Python 经过两个阶段:编译(compilation)执行(execution)

  • 编译阶段:Python 将 increment 函数添加到全局作用域(global scope)
  • 执行阶段:Python 识别 increment() 函数中的 counterbyresult 变量属于局部作用域(local scope),但不会立即创建这些变量,直到函数被调用时才会分配内存。

局部作用域的创建与销毁

每次调用函数时,Python 都会创建一个新的作用域,并将函数内部定义的变量分配到该作用域。这被称为 函数局部作用域(function local scope),简称 局部作用域

例如,当你调用 increment(10,2) 时:

increment(10,2)

Python 进行以下操作:

  1. 创建一个新的局部作用域,用于存储 increment() 调用时的变量。
  2. 创建局部变量 counterbyresult,并将它们分别绑定到 10212
  3. 执行函数,返回 result 值。
  4. 函数执行结束后,Python 会删除这个局部作用域,所有局部变量 counterbyresult超出作用域(out of scope),无法从函数外部访问。

如果你尝试在 increment() 之外访问这些变量,会导致错误

函数每次调用都会创建新的局部作用域

如果再次调用 increment(100,3)

increment(100,3)

Python 不会复用上一次的局部作用域,而是:

  1. 创建新的局部作用域
  2. 重新创建 counterbyresult 变量,并分别绑定到 1003103
  3. 执行函数,返回 result 值。
  4. 函数执行结束后,Python 再次删除这个局部作用域。

每次函数调用,都会有独立的局部作用域,互不影响。

变量查找(Variable lookups)

在 Python 中,作用域是嵌套的(nested)。例如:局部作用域(local scope) 嵌套在 模块作用域(module scope) 内,而 模块作用域 又嵌套在 内置作用域(built-in scope) 内。
在这里插入图片描述

当你访问一个变量所绑定的对象时,Python 按照以下顺序查找该对象:

  1. 首先当前的局部作用域(local scope) 中查找。
  2. 如果找不到,Python 会沿着 嵌套的外层作用域 逐级向上查找,直到找到该对象,或者到达最外层的 内置作用域(built-in scope)

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

global 关键字

当你在函数内部 获取 一个 全局变量 的值时,Python 会 自动 在局部作用域(local scope)查找变量,如果找不到,则继续向上搜索所有 封闭作用域enclosing scopes)中的变量。例如:

counter = 10def current():print(counter)  # 访问全局变量 countercurrent()

在这个例子中,

  • current() 函数运行时,Python 先在局部作用域中查找 counter 变量。
  • 由于 counter 不在局部作用域内,Python 继续在全局作用域中查找,并成功找到 counter = 10,所以输出 10

在函数内修改全局变量

然而,如果 在函数内部赋值 给全局变量,Python 默认会在 局部作用域 创建一个 同名变量,而不是修改全局变量。例如:

counter = 10def reset():counter = 0  # 这里创建了一个局部变量 counterprint(counter)  # 输出 0reset()
print(counter)  # 输出 10(全局变量未被修改)
  • 编译阶段(compile time),Python 认为 reset() 函数内部的 counter局部变量,所以它在 reset() 的作用域中创建了一个新的 counter 变量。

  • reset() 运行时,counter = 0 仅修改了局部作用域的 counter不会影响全局作用域的 counter。 因此,在 reset() 运行后,全局 counter 仍然保持 10

在这个例子中,局部作用域的 counter 遮蔽了全局作用域的 counter

使用 global 关键字修改全局变量

如果你希望在函数内部修改全局变量,需要使用 global 关键字。例如:

counter = 10def reset():global counter  # 告诉 Python 这里的 counter 指的是全局变量counter = 0print(counter)  # 输出 0reset()
print(counter)  # 输出 0

在这个例子中,global counter 语句告诉 Python:counter 变量属于全局作用域,而不是局部作用域。 这样,counter = 0 便会直接修改全局变量 counter,所以 reset() 运行后,全局 counter 也被更新为 0

注意:尽管 global 关键字可以让函数内部修改全局变量,但 这不是一个好的编程实践,更好的做法是:尽量使用函数参数和返回值,而不是直接修改全局变量

nonlocal 关键字

Python 中的 nonlocal 关键字,

  • nonlocal 用于声明 嵌套函数 内部的变量 来自外层函数,而 不是全局作用域
  • 允许修改外层函数作用域中的变量,而 不仅仅是访问 它们。

非局部作用域(Nonlocal scope)

在 Python 中,你可以在一个函数内部定义另一个函数。例如:

def outer():print('outer function')def inner():print('inner function')inner()outer()# outer function
# inner function

在上面的例子中,定义了一个名为 outer 的函数。 在 outer 函数内部,又定义了 inner 函数,并在 outer 函数内部调用 inner。通常,称 inner 嵌套(nested)在 outer 之中。

在实际应用中,当你不希望某个函数是全局可用时,就可以使用嵌套函数

outerinner 函数都能访问:

  • 全局作用域global scope
  • 内置作用域built-in scope
  • 各自的局部作用域local scope

此外,inner 还可以访问 outer 的作用域,这被称为 封闭作用域(enclosing scope

inner() 函数的角度来看,它的封闭作用域 既不是局部作用域(local scope),也不是全局作用域(global scope), Python 将其称为 nonlocal 作用域(非局部作用域)

访问封闭作用域的变量

修改 outerinner 函数,给 outer 添加一个变量 message

def outer():message = 'outer function'  # 定义一个局部变量 messageprint(message)def inner():print(message)  # inner() 访问 outer() 的变量 messageinner()outer()# outer function
# outer function

outer() 执行时:

  1. Python 创建 inner() 函数,但不会立即执行它。
  2. outer() 先打印 message 的值,即 "outer function"
  3. outer() 调用 inner(),开始执行 inner() 内部的代码。
  4. inner() 中,Python 需要查找变量 message
    • 先查找 inner() 的局部作用域,但 inner() 里没有 message
    • 然后查找封闭作用域(outer 的作用域),找到了 message = 'outer function'
    • 成功获取 message 的值,并打印 “outer function”

这种 变量查找规则 称为 LEGB 规则Local → Enclosing → Global → Built-in)。

在这里插入图片描述

看下面的示例:

message = 'global scope'def outer():def inner():print(message)  # 在 inner 函数内部访问 message 变量inner()outer()# global scope

在这个示例中,

  • Python 先在 inner 函数的 局部作用域(local scope) 中查找 message 变量。
  • 由于在 inner 函数的作用域内找不到该变量,Python 继续在封闭作用域(enclosing scope(即 outer 函数的作用域)中查找。
  • outer 函数的作用域中也没有 message 变量,于是 Python 继续向上查找,最终在 全局作用域(global scope) 中找到了 message 变量,并成功打印 "global scope"

在这里插入图片描述

nonlocal 关键字

在局部作用域中修改非局部作用域的变量,可以使用 nonlocal 关键字。例如:

def outer():message = 'outer scope'print(message)def inner():nonlocal messagemessage = 'inner scope'print(message)inner()print(message)outer()# outer scope
# inner scope
# inner scope

在这个示例中,使用 nonlocal 关键字显式地告诉 Python,我们正在修改一个非局部变量。

当你对一个变量使用 nonlocal 关键字时,Python 会 在封闭的局部作用域链中查找该变量,直到第一次遇到这个变量名为止。

更重要的是,Python 不会在全局作用域中查找这个变量

message = 'outer scope'def outer():print(message)def inner():nonlocal messagemessage = 'inner scope'print(message)inner()print(message)outer()

如果运行这段代码,会得到以下错误:

SyntaxError: no binding for nonlocal 'message' found
  • inner 函数内部,对变量 message 使用了 nonlocal 关键字。

  • 因此,Python 会在封闭作用域中查找 message 变量,也就是 outer 函数的作用域。

  • 由于 outer 函数的作用域中并没有 message 变量,并且 Python 不会进一步在全局作用域中查找,所以会报错。

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com