关于python中的nonlocal关键字

如果在函数的子函数中需要调用外部变量,一般会看见一个nonlocal声明,类似下面这种:

def outer_function():x = 10def inner_function():nonlocal xx += 1print(x)inner_function()outer_function()

在这个例子中,inner_function 引用了外部函数 outer_function 中的变量 x,并对其进行了修改。由于涉及修改外部函数的变量,所以需要使用 nonlocal 关键字。

如果在 inner_function 中不使用 nonlocal,而直接对 x 进行修改,Python 将认为 x 是一个新的局部变量,并在 inner_function 中创建一个新的局部变量 x,而不会修改外部函数 outer_function 中的 x。
这个时候运行会出现报错:
在这里插入图片描述
到上面为止都很容易理解。
但是迷惑的点在于我经常看见子函数应用外部变量,但没有进行nonlocal的声明,比如下面这种:

def outer_function():x = [10]def inner_function():x.append(2)print(x)inner_function()
outer_function()

这里inner_function 也引用了外部函数 outer_function 中的变量 x,并对其进行了修改,但并没有声明nonlocal,这是为什么?
原因是:
在这个特定的情况下,x是一个可变对象(列表),而不是不可变对象。在 Python 中,对于可变对象(如列表、字典等),可以在不使用 nonlocal 的情况下在函数内部修改它们的值,因为它们是通过引用传递的。

当你在函数内部修改一个可变对象时,实际上是在原地修改这个对象,而不是重新绑定变量。因此,对于列表 x,你可以在函数内部追加或删除元素,而无需使用 nonlocal。

如果 x是一个不可变对象,例如数字、字符串或元组,你将需要使用 nonlocal 关键字,因为对于不可变对象,重新绑定变量是唯一的方式来修改它们的值。

总的来说,对于可变对象,你可以在函数内部修改它们的值,而不需要 nonlocal 关键字。而对于不可变对象,你通常需要使用 nonlocal 或者返回修改后的值并重新赋给外部变量。

需要注意的事,就算在函数内部引用一个外部的可变对象变量,如果涉及到对该变量的重新赋值,也需要加nonlocal

def outer_function():x = [1,2,3]def inner_function():nonlocal  xx = x+[2]# x.append(2)print(x)inner_function()outer_function()
def outer_function():x =  [1,2,3]def inner_function():# nonlocal  x# x = x+[2]x.append(2)print(x)inner_function()outer_function()

要理解这两者的区别,关键是对于x = []这句的理解,在这里,x 是一个变量,它存储了对列表 [1, 2, 3] 的引用。这表示 x 指向了内存中存储这个列表的位置。而x + [2] 创建了一个新的列表 [1, 2, 3, 2],然后将这个新列表赋给了变量 x。现在,变量 x 指向了一个新的列表对象,发生了重新赋值。所以存在这种重新赋值的情况时,需要加一个nonlocal,这样才能在子函数外部接收到。

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

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

相关文章

【一起来学kubernetes】7、k8s中的ingress详解

引言配置示例负载均衡的实现负载均衡策略实现模式实现方案Nginx类型Ingress实现Treafik类型Ingress实现HAProxy类型ingress实现Istio类型ingress实现APISIX类型ingress实现 更多 引言 Ingress是Kubernetes集群中的一种资源类型,用于实现用域名的方式访问Kubernetes…

万字解析设计模式之责任链模式、状态模式

目录 一、责任链模式 1.1概述 1.2结构 1.3实现 1.4 优缺点 1.5应用场景 1.6源码解析 二、状态模式 2.1概述 2.2结构 2.3实现 2.4优缺点 2.5应用场景 三、责任链模式实验 任务描述 实现方式 编程要求 测试说明 四、状态模式实验 任务描述 实现方式 编程要…

23年最新版pycharm找不到conda可执行文件解决办法

引言 我下载的是2023年最新版本的pycharm,不知道怎么安装pycharm的看我这篇文章。新版的 pycharm 安装好了之后就会出现一个问题,就是在配置 conda 虚拟环境找不到 conda 的可执行文件,出现了以下问题。 遇到这个问题有两种解决办法。 解决办…

ChatGPT文章批量改写伪原创软件说明文档

大家好,我是淘小白~ 最近有很多朋友咨询,chatGPT文章改写插件和改写软件,这个软件之前已经做出来了,用的朋友不是很多,这几天有不少咨询的,现在把说明文档补一下,(#^.^#) 1、软件语言 Pytho…

基于python+TensorFlow+Django算法模型的车辆车型识别系统

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介简介技术栈主要模块1. 数据预处理2. 模型构建3. 模型训练4. 模型集成5. 用户界面 系统工作流程未来改进计划 二、功能三、系统四. 总结 一项目简介 # 车辆车…

5.2每日一题(无穷级数敛散性:绝对收敛、比较法/比较法的极限形式、p级数)

一般看到绝对收敛和条件收敛——先看级数绝对值的敛散性

SpringBoot——配置及原理

优质博文:IT-BLOG-CN 一、Spring Boot全局配置文件 application.properties与application.yml配置文件的作用:可以覆盖SpringBoot配置的默认值。 ◀ YML(is not a Markup Language:不仅仅是一个标记语言)&#xff1…

redis的数据类型的操作增删改查

redis的数据类型的操作增删改查 redis的高可用: 在集群当中有一个非常重要的指标,提供正常服务的时间的百分比(365天)99.9% redis的高可用的含义要更加宽泛,正常服务是指标之一数据容量扩展,数据的安全性…

一起学docker系列之八使用 Docker 安装配置 MySQL

目录 前言步骤 1:拉取 MySQL 镜像步骤 2:运行 MySQL 容器步骤 3:检查容器状态步骤 4:进入 MySQL 容器步骤 5:配置 MySQL 字符编码步骤 6:重启 MySQL 容器步骤 7:测试字符编码步骤 8:…

如何使用Python在3dMax控制网格对象?

我们以一个在3dMax中使用Python脚本在网格对象对象上创建水波变形作为例子。 首先,在3dmax创建两个对象,一个“box”对象,将长宽方向的分段设置的多一些(目的是为了后面的水波变形),一个“点”帮助对象&am…

王者农药小游戏

游戏运行如下: sxt Background package sxt;import java.awt.*; //背景类 public class Background extends GameObject{public Background(GameFrame gameFrame) {super(gameFrame);}Image bg Toolkit.getDefaultToolkit().getImage("C:\\Users\\24465\\D…

辅助驾驶功能开发-系统方案篇-地平线超级驾驶解决方案介绍

01.产品方案 Horizon Matrix SuperDrive超级驾驶解决方案,助力汽车智能化步入人机共驾时代 SuperDrive超级驾驶解决方案,全面整合了自动驾驶、智能交互、云端大脑三大模块,形成完整的泛车载AI人工智能系统,帮助整车智能化提升到一个新的高度。该方案的核心硬件-车载中央计…