【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)路由选择:网络环境比较复杂,从一个节点到另一个节点,存在很多条不同的路径,需要规划出…

《算法ZUC》题目

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

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", //需要添加的…

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

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

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

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

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

1、图块调色板(Tile Palette)可以在以下位置找到: Tileset Inspector检视面板 STETilemap Inspector检视面板,并选择 "Paint" 选项卡 Tile Palette 窗口:"SuperTilemapEditor/Window/Tile Palette Win…

LNMP+discuz论坛

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

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

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

开源架构学习指南:文档与资源的智慧锦囊

开源架构学习指南:文档与资源的智慧锦囊 一、引言二、开源架构文档的核心价值剖析(一)知识传承与共享:智慧的薪火相传1. 经典案例:Linux 内核文档 —— 开源世界的智慧基石 (二)促进协作与沟通&…

景联文科技:精准语音标注,驱动语音技术新发展

在人工智能迅速发展的今天,语音技术的应用已经渗透到我们生活的方方面面。从智能音箱、语音助手到自动语音识别系统,高质量的语音数据是这些应用成功的关键。景联文科技作为领先的AI数据服务提供商,专注于为客户提供高精度、高效的语音标注服…

HTTP接口报错详解与解决 200,500,403,408,404

前言: 仅做学习记录,侵删 背景 当后端编写接口时,经常需要对接口使用ApiFox或者PostMan进行测试,此时就会出现各种各样的报错,一般都会包括报错编码:200,400,401等。这个状态码一般是服务器所返回的包含…

NVIDIA发布紧凑型生成式AI超级计算机:性能提升,价格更低

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

upload-labs(1-19关)通关攻略

Pass-01 本关思路&#xff1a;删除前端js校验 进入第一关环境 桌面新建一个php文件&#xff0c;命名为1.php <?php eval($_POST[a]);?> 我们上传此文件&#xff0c;发现不允许上传&#xff0c;且页面没有变化&#xff0c;说明前端进行了拦截 这时我们打开 F12 &…

【开源库 | minizip】Linux(Ubuntu18.04)下,minizip的编译、交叉编译

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a; 2024-12-20 …

uniapp地址类 方法

关于点击没反应 manifest.json 检查是否添加了对应的权限 /* 小程序特有相关 */"mp-weixin" : {"appid" : "wxc481f10754f1d9df","setting" : {"urlCheck" : false,"es6" : true,"postcss" : true,&qu…

WebContainerapi 基础(Web IDE 技术探索 一)

前言 随着web技术的发展&#xff0c;在网页端直接运行node.js、实现微型操作系统已经不再是难事。今天介绍的 WebContainers就是一个基于浏览器的运行时&#xff0c;用于执行 Node.js 应用程序和操作系统命令&#xff0c;它完全运行在您的浏览器页面中&#xff0c;提供了文件系…

【爬虫开发】爬虫开发从0到1全知识教程第11篇:Mongodb数据库,介绍【附代码文档】

本教程的知识点为&#xff1a;爬虫概要 爬虫基础 爬虫概述 知识点&#xff1a; 1. 爬虫的概念 requests模块 requests模块 知识点&#xff1a; 1. requests模块介绍 1.1 requests模块的作用&#xff1a; 数据提取概要 数据提取概述 知识点 1. 响应内容的分类 知识点&#xff1a…