【Python函数】对 LEGB 规则以及 nonlocal 和 global 语法的掌握

def outter():def innerA():x = 100def innerB():nonlocal xx = 250def innerC():global xx = 520x = 880innerA()print(f"调用完 innerA() 函数之后,x = {x}")innerB()print(f"调用完 innerB() 函数之后,x = {x}")innerC()print(f"调用完 innerC() 函数之后,x = {x}")outter()print(f"此时此刻,全局变量 x = {x}")
调用完 innerA() 函数之后,x = 880调用完 innerB() 函数之后,x = 250调用完 innerC() 函数之后,x = 250此时此刻,全局变量 x = 520

 


在这个代码中,我们通过嵌套函数以及不同作用域(LEGB:Local、Enclosing、Global、Built-in)来理解变量 x 的变化。接下来,我会逐行分析,并结合 Python 中 nonlocal 和 global 的规则来解释每一行代码的执行结果。

def outter(): def innerA(): x = 100 def innerB(): nonlocal x x = 250 def innerC(): global x x = 520 x = 880 innerA() print(f"调用完 innerA() 函数之后,x = {x}") innerB() print(f"调用完 innerB() 函数之后,x = {x}") innerC() print(f"调用完 innerC() 函数之后,x = {x}") outter() print(f"此时此刻,全局变量 x = {x}")

逐行分析:

def outter():

定义了一个名为 outter 的外部函数。

def innerA():

定义了一个名为 innerA 的内部函数。

x = 100

在 innerA() 中声明了一个局部变量 x = 100,但这个 x 仅在 innerA() 函数内部存在。

def innerB():

定义了另一个名为 innerB 的内部函数。

nonlocal x

这里使用 nonlocal 关键字,表示要修改的是 outter() 函数作用域中的 x,而不是 innerB() 内部的局部变量。如果 nonlocal 没有找到外部作用域的变量,它会抛出 SyntaxError。

x = 250

在 innerB() 中修改了 outter() 函数作用域中的 x 为 250。

def innerC():

定义了名为 innerC 的内部函数。

global x

这里使用 global 关键字,表示要修改的是全局作用域中的 x。这意味着 innerC() 中对 x 的修改将会影响全局变量 x。

x = 520

在 innerC() 中将全局变量 x 的值改为 520。

x = 880

在 outter() 中定义了一个局部变量 x = 880,这是 outter() 的作用域内的 x,它与 innerA()、innerB() 和 innerC() 函数的 x 是不同的。

innerA()

调用 innerA(),但由于 innerA() 只改变了 innerA() 内部的 x,而没有影响到 outter() 中的 x(因为 x = 100 是局部变量),所以 outter() 中的 x 依然保持为 880。

输出结果是:调用完 innerA() 函数之后,x = 880

innerB()

调用 innerB()。在 innerB() 中,nonlocal x 会改变 outter() 中的 x 为 250。因此,outter() 中的 x 变成了 250。

输出结果是:调用完 innerB() 函数之后,x = 250

innerC()

调用 innerC()。在 innerC() 中,global x 会改变全局变量 x 的值为 520。因此,x 在全局作用域中的值变成了 520。

输出结果是:调用完 innerC() 函数之后,x = 250 这里的 x = 250 是 outter() 作用域中的 x,而不是全局变量。

outter()

调用 outter() 函数结束后,函数内部的所有局部变量和作用域都将被销毁。但全局变量 x 已经被 innerC() 修改为 520。

print(f"此时此刻,全局变量 x = {x}")

输出全局变量 x 的值,此时全局变量 x 已经被 innerC() 修改为 520。

输出结果是:此时此刻,全局变量 x = 520

输出结果:

调用完 innerA() 函数之后,x = 880 调用完 innerB() 函数之后,x = 250 调用完 innerC() 函数之后,x = 250 此时此刻,全局变量 x = 520

解释:

LEGB规则:

L(Local):局部作用域。x = 100 在 innerA 内部作用域,只在 innerA 内部有效。

E(Enclosing):外层作用域。nonlocal 会改变外层作用域(即 outter())中的 x。

G(Global):全局作用域。global 会影响全局作用域中的 x。

nonlocal:

用来引用最近的外层函数(非全局)作用域中的变量,修改它的值。

在 innerB 中,nonlocal x 修改了 outter() 作用域中的 x。

global:

用来引用全局作用域中的变量,修改它的值。

在 innerC 中,global x 修改了全局作用域中的 x。


在 Python 中,`LEGB` 规则用于确定变量的查找顺序。具体来说,`LEGB` 代表:

- **L** (Local):当前函数或代码块内的局部变量。
- **E** (Enclosing):外层函数的局部变量(即封闭作用域)。
- **G** (Global):模块级别的全局变量。
- **B** (Built-in):Python 预定义的内建变量和函数。

当 Python 执行变量查找时,它会按照 **LEGB** 的顺序查找,直到找到该变量为止。如果一个变量在某个作用域中没有定义,Python 会继续向外层作用域查找,直到最外层的内建作用域。

### `global` 和 `nonlocal` 的作用

- **`global`**:用来声明某个变量是在 **全局作用域**(模块级别)中,而非当前函数的局部变量。如果你在一个函数中使用 `global` 声明一个变量,Python 会把这个变量视为全局变量,从而可以修改全局作用域中的该变量。
 
- **`nonlocal`**:用来声明某个变量是在 **封闭作用域**(即外层函数的局部作用域)中,而非当前函数的局部变量。如果你在嵌套函数中使用 `nonlocal`,Python 会把这个变量视为外层函数(而不是全局作用域)中的变量,并且可以修改它。

### `global` 和 `nonlocal` 会冲突吗?

**会冲突,但只有在它们操作同一个变量时才会有问题。**

- **`global`** 和 **`nonlocal`** 不会直接冲突,但是它们的使用方式和适用范围是不同的。
  - `global` 会操作全局作用域中的变量。
  - `nonlocal` 会操作外层(非全局)作用域中的变量。

如果你在同一个函数中同时使用 `global` 和 `nonlocal` 来声明同一个变量,则会产生 **冲突**,因为它们作用于不同的作用域(`global` 修改全局变量,而 `nonlocal` 修改外层作用域中的变量),这可能导致意外的行为或错误。

### 示例:`global` 和 `nonlocal` 的冲突

```python
x = 10  # 全局变量

def outer():
    x = 20  # outer 函数中的局部变量
    
    def inner():
        nonlocal x  # 尝试修改 outer 中的 x
        global x     # 尝试修改全局变量 x
        x = 30       # 这将修改 outer 中的 x
        print(f"inner 函数中的 x = {x}")
    
    inner()
    print(f"outer 函数中的 x = {x}")

outer()
print(f"全局变量 x = {x}")
```

### 分析:
1. 在 `outer()` 函数内,`x = 20` 是 `outer` 局部作用域中的变量。
2. `inner()` 中使用了 `nonlocal x` 来修改 `outer()` 中的 `x`,同时又使用 `global x` 来修改全局变量 `x`。
3. `nonlocal x` 会修改 `outer()` 中的 `x`,而 `global x` 会修改全局变量 `x`。

### 输出:

```python
inner 函数中的 x = 30
outer 函数中的 x = 30
全局变量 x = 30
```

### 解释:
- 在 `inner()` 中,`nonlocal x` 让 Python 修改 `outer()` 中的 `x`,将其变为 30。
- `global x` 将全局变量 `x` 的值也修改为 30。
- 最终,`outer()` 中的 `x` 和全局变量 `x` 都变成了 30。

### 是否会引发错误?

在上述代码中,虽然 `global` 和 `nonlocal` 分别操作了不同作用域中的 `x`,所以它们并不会直接冲突。不过,如果你试图同时在同一个作用域中使用 `global` 和 `nonlocal` 来声明相同的变量,就会引发 **`SyntaxError`**。

例如:

```python
def foo():
    nonlocal x
    global x  # 这将导致语法错误
```

### 总结:
- **`global` 和 `nonlocal` 不会直接冲突**,但它们作用于不同的作用域。
- 如果同时在同一个函数中尝试使用 `global` 和 `nonlocal` 来修改同一个变量,它们会分别修改不同作用域中的变量,可能会导致混乱和错误。
- Python 不允许在同一个作用域内同时使用 `global` 和 `nonlocal` 来声明同一个变量,这会导致 `SyntaxError`。


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

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

相关文章

java_零钱通项目

SmallChangeSysOOP.java package com.hspedu.smallchange.oop;import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner;/*** 该类是完成零钱通的各个功能的类* 使用OOP(面向对象编程)*/ public class SmallChangeSysOOP {// 定义相关…

Mamba安装环境和使用,anaconda环境打包

什么是mamba Mamba是一个极速版本的conda,它是conda的C重新实现,使用多线程并行处理来加速包和依赖项的下载。 Mamba旨在提高安装、更新和卸载Python包的速度,同时保持与conda相同的兼容性和命令行接口。 Mamba的核心部分使用C实现&#xff…

网络多层的协议详述

网络层 1)地址管理:制定一系列的规则,通过地址,在网络上描述出一个设备的位置 2)路由选择:网络环境比较复杂,从一个节点到另一个节点,存在很多条不同的路径,需要规划出…

【异常】GL-SFT1200路由器中继模式,TL-CPE1300D无法搜寻5G网问题分析

【异常】GL-SFT1200路由器中继模式,TL-CPE1300D无法搜寻5G网问题 情况实验结论情况 在用GL-SFT1200路由器切换中继模式时,由于web密码忘却,需要重置,但根据官网使用手册,或者对应的中文版手册,重置失败。通过跟商家联系,进行uboot刷机,提供了指导文档,尝试后刷机成功…

《算法ZUC》题目

判断题 ZUC算法LFSR部分产生的二元序列具有很低的线性复杂度。 A.正确 B.错误 正确答案A 单项选择题 ZUC算法驱动部分LFSR的抽头位置不包括( )。 A.s15 B.s10 C.s7 D.s0 正确答案C 单项选择题 ZUC算法比特重组BR层主要使用了软件实现友好的…

交换机vlan划分以及端口隔离

vlan 1、基于接口划分vlan 2、基于mac地址划分vlan (接口最好设置为hybird,如果是access和trunk的话,当mac地址匹配到的vlan跟接口的pvid不一致时,不允许通过;而hybird口可以很好的支持多个vlan去除tag后直连设备) #在vlan视…

Flink SQL 从一个SOURCE 写入多个Sink端实例

一. 背景 FLINK 任务从一个数据源读取数据, 写入多个sink端. 二. 官方实例 写入多个Sink语句时,需要以BEGIN STATEMENT SET;开头,以END;结尾。--源表 CREATE TEMPORARY TABLE datagen_source (name VARCHAR,score BIGINT ) WITH (connector datagen …

.vscode配置文件备份

vscode插件 位于:C:\Users\用户名\AppData\Roaming\Code\User\settings.json settings.json {// "C_Cpp.intelliSenseEngine": "default",//智能查找默认值"C_Cpp.intelliSenseEngineFallback": "enabled", //需要添加的…

(Image Signal Processor)ISP简介

文章目录 ISP功能简介ISP的主要功能ISP的主要模块1. **黑电平校正(Black Level Correction, BLC)**2. **噪声去除(Denoise)**3. **色彩校正(Color Correction Matrix, CCM)**4. **自动曝光(Auto…

代码随想录day23 | leetcode 39.组合总和 40.组合总和II

39.组合总和 Java class Solution { List<List<Integer>> result new ArrayList<>();LinkedList<Integer> path new LinkedList<>();public List<List<Integer>> combinationSum(int[] candidates, int target) {Arrays.sor…

将HTML转换为PDF:使用Spire.Doc的详细指南

目录 引言 1. 为什么选择 Spire.Doc&#xff1f; 1.1 主要特点 1.2 适用场景 2. 准备工作 2.1 引入 Spire.Doc 依赖 2.2 禁用 SSL 证书验证 3. 实现功能 3.1 主类结构 3.2 代码解析 4. 处理图像 5. 性能优化 5.1 异步下载图像 示例代码 5.2 批量处理优化 示例代…

jmeter监控服务器性能信息

概述 Apache JMeter 是一个功能强大的开源工具,主要用于进行压力测试和性能测试。除了用于模拟用户行为进行压力测试外,JMeter 还提供了一些功能来监控服务器性能。 性能测试时我们关注的重要指标是:并发用户数,TPS,请求成功率,响应时间,服务器的CPU,memory, l/0 dis…

关于Buildroot如何配置qtwebengine [未能成功编译]

目录 前言 下载Buildroot 如何添加qtwebengine 开始make编译 编译过程中到了这些问题 前言 问题的开始就在于学习QT的过程中遇到了一个问题… Unknown module(s) in QT: webenginewidgets 我想要把qt的一个项目编译并发送到我的开发板上&#xff0c;但是qmake识别不到这…

SNP与Scheer合作助力Warsteiner Brauerei成功升级至SAP S/4HANA

德国软件和咨询公司SNP是SAP环境中数字化转型、自动化数据迁移和数据管理软件的知名提供商&#xff0c;再次与德国Scheer公司合作&#xff0c;Scheer公司是一家专门从事业务流程管理和SAP咨询的咨询公司。他们为家族企业Warsteiner Brauerei Haus Cramer KG向SAP S/4HANA升级转…

Apache Samza开源的分布式流处理框架

Apache Samza 是一个开源的分布式流处理框架,用于处理实时数据流和分布式任务。它最初由 LinkedIn 开发,并在 2014 年捐赠给 Apache 软件基金会。Samza 的设计目标是为开发人员提供一个易用、可靠、高效的流处理工具。以下是其关键特点和架构的简介: 核心特点 简单的编程模…

【Super Tilemap Editor使用详解】(五):图块调色板

1、图块调色板&#xff08;Tile Palette&#xff09;可以在以下位置找到&#xff1a; Tileset Inspector检视面板 STETilemap Inspector检视面板&#xff0c;并选择 "Paint" 选项卡 Tile Palette 窗口&#xff1a;"SuperTilemapEditor/Window/Tile Palette Win…

LNMP+discuz论坛

0.准备 文章目录 0.准备1.nginx2.mysql2.1 mysql82.2 mysql5.7 3.php4.测试php访问mysql5.部署 Discuz6.其他 yum源&#xff1a; # 没有wget&#xff0c;用这个 # curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo[rootlocalhost ~]#…

kylinos如何使用udev修改网卡名称

在KylinOS中使用udev修改网卡名称可以按照以下步骤进行操作: 查看网卡信息 在终端中输入ip a或ifconfig -a命令,查看当前系统中的网卡设备及其MAC地址等信息,记录要修改名称的网卡的MAC地址。创建udev规则文件 以root用户身份或使用sudo权限创建一个udev规则文件。可以在/e…

TRELLIS,一键生成3D模型,图像转3D,微软开源

大家好&#xff01;今天给大家分享微软最近开源的一个3D模型生成项目——TRELLIS。简单来说就是输入一张图片&#xff0c;它就能自动帮你生成3D模型。这与之前分享的TripoSR项目类似&#xff0c;但是精度和贴图细节比TripoSR要高很多。 好久没关注AI生成3D模型这块&#xff0c;…

ios swift 开发系列--如何把粤语转语音

在Swift中&#xff0c;我们可以使用AVSpeechSynthesizer进行文本到语音的转换&#xff0c;我们通过设置AVSpeechUtterance的voice属性来指定朗读的语言和口音。 要确保朗读的是粤语&#xff0c;我们应该使用一个特定的语言代码&#xff0c;例如"zh-Hant-HK"&#xf…