Python里的全局变量、局部变量、类的self.*

问题

困惑,leetcode第538题,写成下面这种,不能得到正确的答案:

class Solution_a:def traverse(self, root, cur_sum):# 思路:中序遍历可以打印出有序的数组,那么反一下,先右后中再左就可以打印出降序的数组,然后再维护一个字段记录累计和if not root:returnself.traverse(root.right, cur_sum)cur_sum += root.valroot.val = cur_sumself.traverse(root.left, cur_sum)returndef convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:global cur_sumcur_sum = 0self.traverse(root, cur_sum)return root

但是改成下面这样(将cur_sum初始化为一个属性),就可以了:

class Solution_a:def __init__(self):self.cur_sum = 0def traverse(self, root):# 思路:中序遍历可以打印出有序的数组,那么反一下,先右后中再左就可以打印出降序的数组,然后再维护一个字段记录累计和if not root:returnself.traverse(root.right)self.cur_sum += root.valroot.val = self.cur_sumself.traverse(root.left)returndef convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:self.traverse(root)return root

思考

本质的区别和原因是什么呢?

第一种写法下,我以为是:我在convertBST函数里定义了一个全局变量cur_sum(后面会醒悟这个以为也是错误的,因为全局变量不会在一个函数内部去定义),但是调用traverse时,cur_sum是以一个参数的形式传入的,当函数内部存在一个与全局变量同名的局部变量时,会使用自己内部的局部变量。举个二叉树的例子,用第一种写法调用的结果是:
在这里插入图片描述

如果这个以为是对的话,那我不把cur_sum以参数的形式传入应该就行了,试试看:
在这里插入图片描述
报错如下,这说明全局变量就不是这么定义的,不然traverse内部怎么找不到它?在这里插入图片描述

不死心,我尝试再改一下这个定义的位置看看:
在这里插入图片描述

依然不行!!还不死心,我再改一下位置,直接放在调用的地方试试:
在这里插入图片描述

依然不对!!!说明global 变量名 并不是我以为的用来定义一个全新的全局变量,然后就到处可以用了!global到底怎么用,问问GPT的到如下回复:

在Python中,global关键字用于在函数内部声明一个全局变量,以便在函数内部对全局变量进行修改。

好的,小菜鸡认为自己悟了,再给我一次机会,修改成下图,老老实实的在所有函数外部定义一个全局变量,在traverse中想要更改全局变量时,使用global关键字(如果没有将其声明为全局变量,则在函数内部更改或创建的任何变量都是局部变量),规范操作:
在这里插入图片描述

!!!啊啊啊,它终于对了!但是刷leetcode的时候不方便这么写啊,因为调用的代码在外面,不是咱自己写的呢。所以还是老老实实用第二种方法吧。

第二种写法self.cur_sum相当于在一开始,就初始化了一个属性,在类的所有函数里都可以调用(很像全局变量的感觉),所以可以得到正确结果。
在这里插入图片描述

总结

  1. 全局变量的定义:没有在任何函数内部定义,并且具有全局范围的变量;
  2. 局部变量的定义:在函数内部定义的变量,范围仅限于该函数;
  3. python中global关键字的用法:是在一个函数内部声明一个全局变量,以便在函数内部对全局变量进行修改,这个全局变量本身已经定义过了,而不是我想当然认为的定义了一个全新的全局变量!‼️如果没有将其声明为全局变量,则在函数内部更改或创建的任何变量都是局部变量。
  4. 当全局变量和局部变量的命名一样时,在一个函数内部还是会使用自己内部的局部变量;

问题延伸

那怎么理解下面这段代码里root的更新呢?root以一个参数的形式传递给了traverse,在traverse的内部修改了节点的value,这些修改的操作最终在convertBST函数里返回,为什么也可以生效?(原地修改的原理)

因为root是可变对象,具体见下图。在函数内部修改树的节点值时,即使没有显式的返回root,原始的root也会被更新。
在这里插入图片描述

class Solution_a:def __init__(self):self.cur_sum = 0def traverse(self, root):# 思路:中序遍历可以打印出有序的数组,那么反一下,先右后中再左就可以打印出降序的数组,然后再维护一个字段记录累计和if not root:returnself.traverse(root.right)self.cur_sum += root.valroot.val = self.cur_sumself.traverse(root.left)returndef convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:self.traverse(root)return root

参考资料

  1. Python全局变量和局部变量
  2. Python中的值类型与引用类型

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

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

相关文章

YOLOv8独家原创改进:特征融合涨点篇 | 广义高效层聚合网络(GELAN) | YOLOv9

💡💡💡本文独家改进:即结合用梯度路径规划(CSPNet)和(ELAN)设计了一种广义的高效层聚合网络(GELAN),高效结合YOLOv8,实现涨点。 将GELAN添加在backbone和head处,提供多个yaml改进方法 💡💡💡在多个私有数据集和公开数据集VisDrone2019、PASCAL VOC实现…

类变量【静态变量 static】

类变量【静态变量 static】 什么是类变量如何定义类变量如何访问类变量类变量使用注意事项和细节 什么是类变量 类变量,也叫静态属性/静态变量,是该类的所有对象共享的变量;   1)任何一个该类的对象去访问它时,取到的…

DAY 11有效括号 删除字符串中的相邻重复项 逆波兰表达式

3.有效的括号 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的…

eclipse搭建java web项目

准备条件 eclipsejdk1.8 (配置jdk环境)apache-tomcat-8.5.97(记住安装位置) 一 点击完成 开始创建javaweb项目 import java.io.IOException; import java.io.PrintWriter;import javax.servlet.ServletException; import javax.s…

CAD图纸归档平台、CAD图纸归档系统

CAD图纸归档平台是用于管理和存储CAD图纸的在线平台。这些平台提供了多种功能,包括图纸上传、下载、版本控制、共享、协作和搜索等。它们可以大大提高CAD图纸的管理效率和协作效率,减少纸质图纸的使用和存储成本,同时也方便用户随时随地访问和…

关于python函数参数传递

参数传递 在 python 中,类型属于对象,对象有不同类型的区分,变量是没有类型的: 在下面的代码示例重,[1,2,3] 是 List 类型,“qayrup” 是 String 类型,而变量 a 是没有类型,它仅仅…

奥维云网:森歌智能水洗集成灶开启集成灶4.0时代

新的一个商业“竞争年”正式到来。厨电集成灶行业率先发力。2曰27日,森歌以“勠力同心,共生共歌”为主题召开了盛大的全国优秀经销商峰会,并在峰会上一连发布了三个重磅消息,被视为集成灶行业的破冰行动! 从国家统计局…

MySQL 学习记录 2

原文:https://blog.iyatt.com/?p13818 13 存储引擎 查看一下前面创建的一张表的创建语句,当时并没有显式指定引擎,MySQL 自动指定的 InnoDB,即默认引擎是这个。 创建表的时候要显式指定引擎可以参考这个语句 查看当前 MySQL …

深度学习GPU环境安装(WINDOWS安装NVIDIA)

1.检测是否支持GPU环境 1.1.打开设备管理器 winows下面搜索设备管理器(或者从桌面"此电脑"——>右键点击——>"管理"打开) 1.2.查看本地显卡 在"设备管理器"——"显示适配器"中,如果没有&…

【LeetCode】升级打怪之路 Day 14:二叉树的遍历

今日题目: 144. 二叉树的前序遍历94. 二叉树的中序遍历145. 二叉树的后序遍历102. 二叉树的层序遍历 目录 Problem 1:二叉树的递归遍历 【easy】Problem 2:二叉树的迭代遍历 【classic】2.1 前序遍历 迭代版2.2 中序遍历 迭代版2.3 后序遍历 …

大语言模型在科技研发与创新中的角色在快速变化

在技术研发与创新中,比如在软件开发、编程工具、科技论文撰写等方面,大语言模型可以辅助工程师和技术专家进行快速的知识检索、代码生成、技术文档编写等工作。在当今的软件工程和研发领域,尤其是随着大语言模型技术的快速发展,它…

Qt for WebAssembly : Application exit (SharedArrayBuffer is not defined)

用Qt开发 WebAssembly,放到nginx里面,用127.0.0.1访问没问题,用局域网IP访问就提示如下: 总结了以下两种解决办法: ①:配置 nginx http 头 [ 支持:WebAssembly Qt (single-threaded) ] ②&#…