Python番外篇:变量是盒子还是标签

引言

前面通过几十篇文章,大概把Python的一些比较实用的基础做了一些介绍,学会这些,基本能应付日常的小的需求开发了,写一些小工具,提高工作的处理效率。

接下来,准备开始进入一个新的篇章,也就是Python的面向对象了。

但是,在开始介绍Python面向对象之前,还是需要对变量这个从开始学一直到每次写代码都要用到的概念,再稍微唠叨一番。

因为,很多编程自学者,哪怕写了挺多的代码了,其实对变量还是一知半解的状态。

变量的盒子比喻

有些教材在介绍变量是,经常将变量比喻为盒子,变量的值,为盒子中所保存的内容。这对于静态语言中的普通变量来说,是合适的。但是,对理解面向对象语言中的引用型变量,会造成理解上的困扰。

如果变量是盒子,那以下的代码是不可解释的:

# 如果变量是盒子,现在有一个盒子叫a,这个盒子里面装着[1, 2, 3]
a = [1, 2, 3]
# 有一个新的盒子,叫b,这个盒子里面也装着[1, 2, 3]
b = a
# 目前来说,从print输出来看,盒子的比喻都是没有问题的
print(a)
print(b)
# 但是,当我们修改了b[0]时,盒子的比喻无法解释了
b[0] = 100
print(b)
# 我们只是修改了b盒子的元素,为什么a盒子的也变了
print(a)

执行结果:

02f35c4b645ff8ff0c42b3cb993e2084.jpeg

变量的标签比喻

既然变量是盒子的比喻,解释不通了,我们对于变量的理解,必须换一个思路去理解。

在Python中一切皆是对象,变量是跟对象进行绑定的,这种绑定关系又是可以改变的,也许把变量理解成贴在对象上的便签纸,也许更加容易理解。

e0f74cfce290e351ec770355704baadd.jpeg

注:标签比喻及对应的图片来源于《流畅的Python》。

垃圾就该待在垃圾箱里

我们在Python代码中,使用任何对象,都是通过变量来实现的。一个对象上有一个变量与之对应,也就是贴了一个标签,在Python中叫做存在一个对该对象的引用。有多个变量与这同一个对象产生了对应,也就是有多个对该对象的引用。

那么,问题来了,如果一个内存中的对象上没有贴任何标签,也就是没有任何变量与之对应,也就是对该对象的引用数为0,那么这个对象我们可以使用吗?

答案显然是否定的,因为我们根本无法找到这个对象,那么这个对象在内存中,占用着存储空间,却没有任何用,那就是内存垃圾了,垃圾就应该待在垃圾箱里。

所以,最基础、最朴素的内存回收就是基于对象的引用计数实现的,当一个对象的引用计数为0,则这个对象被标记为垃圾,在特定的时机,会出发垃圾回收机制,将之从内存中释放。

在Python中,可以通过sys.getrefcount()函数,获取一个对象的引用,但是,需要注意的是:getrefcount()函数返回的计数会比实际引用计数多一个,因为它包含了作为参数传递给getrefcount()函数时创建的临时引用。

import sys
a = [1, 2, 3]
print(sys.getrefcount(a))
b = a
print(sys.getrefcount(a))
c = a
print(sys.getrefcount(a))
# del操作,并不是删除对象,而是解除变量对对象的引用
del c
print(sys.getrefcount(a))
# 重新赋值操作,也会解除对原对象的引用
b = 123
print(sys.getrefcount(a))

执行结果:

dfa11f99aa9ef3c5b98f41f59752815b.jpeg

通过引用计数,我们可以知道,此前对del操作的理解,其实可能也是有些偏差的。

del操作,只是解除该变量与某个对象对应的引用关系,对象的引用计数会减少,但并不是字面意思上的删除对象。即使当前变量是对某个对象的最后一个引用了,del之后引用计数为0了,也不是立马进行垃圾回收。而是,在恰当的时机,比如定时或者内存空间不足时,才会触发垃圾回收。

而且,垃圾回收并不是必须的(如果内存足够),垃圾回收必须满足的一个质量保证是,不能将还在使用的对象当做垃圾进行回收。

对象的比较

既然变量本身是对对象的引用,两个变量的比较,其本质是对引用对象的比较。

关于比较,在编程中有两种,一种叫同一性比较,一种叫相等性比较。

同一性比较,是判断两个变量是不是对同一个对象的两个引用、两个标签而已,同一性,显然是隐含相等性的。

相等性比较,是判断两个对象的值/内容是否相等。

a = [1, 2, 3]
b = a
c = [1, 2, 3]
# 同一性比较,通过is实现
print(a is b)
print(a is c)# 相等性比较,通过==实现
print(a == b)
print(a == c)

执行结果:

2d06803fb6b916e44673d460ac51fe6e.jpeg

==进行的相等性判断,其实是Python中的语法糖,本质上是通过__eq__()魔法函数来实现的。所以,如果是自定义的对象,可以通过实现__eq__()函数,来实现自定义相等性的语义判断。

总结

本文将变量与对象的关系,做了进一步的解析,同时稍微提及了关于Python中的对象引用计数与垃圾回收的概念,并对对象的两种比较方式进行了简单的解释说明。

a0dd7f9e3a8f30048d1c4a00d98d1334.jpeg

在接下来的文章中,我们将进入Python新的篇章“面向对象”的介绍。

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

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

相关文章

del 语句

使用 del 语句可以删除任何对象,包括字典对象。删除之后,之前的引用将失效,尝试使用该对象会导致 NameError 错误。因此,删除字典对象的命令是 del myDict。 元组 (Tuple) 元组是不可变的,因此你不能修改元组的内容&a…

C#如何引用dll动态链接库文件的注释

1、dll动态库文件项目生成属性中要勾选“XML文档文件” 注意:XML文件的名字切勿修改。 2、添加引用时XML文件要与DLL文件在同一个目录下。 3、如果要是添加引用的时候XML不在相同目录下,之后又将XML文件复制到相同的目录下,需要删除引用&am…

MySQL之索引优化

1、在进行查询时,索引列不能是表达式的一部分,也不能是函数的参数,否则无法使用索引 例如下面的查询不能使用 actor_id 列的索引: #这是错误的 SELECT actor_id FROM sakila.actor WHERE actor_id 1 5; 优化方式:…

微信小程序安装vant组件库和使用

第一步打开终端输入 npm install vant/weapp --save 第二步 npm cache clean --force 第三步 npm i vant/weapp -S --production 第四步在app.json中的usingComponents输入 "van-button": "vant/weapp/button/index" 第五步直接在页面使用 <v…

SSM(Spring + Spring MVC + MyBatis)框架面试三道题

以下是三道关于SSM&#xff08;Spring Spring MVC MyBatis&#xff09;框架的面试题&#xff0c;由简单到困难进行排列&#xff1a; 1. 简答题&#xff1a;请简述Spring框架的核心特性。 答案&#xff1a; Spring框架的核心特性主要包括以下几个方面&#xff1a; 控制反转…

当设计模式牵手LLM

模版方法模式 何为模版设计模式 想象一下 如果我们要泡一杯茶 我们要循序渐进地 煮水温杯注水浸茶茶水入杯加点配料 如此&#xff0c;泡茶的工序就完成了&#xff0c;那么模板方法模式&#xff0c;相信各位也有了一定的概念&#xff1a;定义了一个算法的骨架&#xff0c;而…

UDP的报文结构及其注意事项

1. 概述 UDP&#xff08;User Datagram Protocol&#xff09;是一种无连接的传输层协议&#xff0c;它提供了一种简单的数据传输服务&#xff0c;不保证数据的可靠传输。在网络通信中&#xff0c;UDP通常用于一些对实时性要求较高、数据量较小、传输延迟较低的应用&#xff0c…

创建一个程序来记录每天的工作日常—6。与chatgpt结合 找一些集 来训练 ,它能自动分类到 其中一个,例如 “打扫卫生” 它会自动分类到 “家务”

改进步骤 数据增强&#xff1a;使用GPT模型生成更多的训练数据。使用更高级的模型&#xff1a;使用BERT或其他预训练的语言模型进行文本分类。经验条和经验值显示&#xff1a;在网页端显示当前的经验值&#xff0c;并添加一个经验条。 数据增强和训练数据集 我们可以通过Ope…

【JVM基础07】——类加载器-什么是类加载器?类加载器有哪些?双亲委派了解吗?

目录 1- 引言&#xff1a;类加载器1-1 类加载器是什么&#xff1f;(What)1-2 为什么要用类加载器&#xff1f; 作用&#xff1a;类加载的过程&#xff1f;(Why) 2- ⭐核心&#xff1a;类加载器详解(How)2-1 类加载器分类2-2 什么是双亲委派模型&#xff1f;2-3 为什么采用双亲委…

Pytorch基础:Tensor的squeeze和unsqueeze方法

相关阅读 Pytorch基础https://blog.csdn.net/weixin_45791458/category_12457644.html?spm1001.2014.3001.5482 在Pytorch中&#xff0c;squeeze和unsqueeze是Tensor的一个重要方法&#xff0c;同时它们也是torch模块中的一个函数&#xff0c;它们的语法如下所示。 Tensor.…

【SpringBoot】1 Gitee

本项目 Gitee 地址&#xff1a;https://gitee.com/Lin_DH/system idea中可能装个gitee的插件&#xff0c;这样操作起来比较方便。 1&#xff09;登录 Gitee 官网&#xff08;https://gitee.com/&#xff09;&#xff0c;新建仓库。 2&#xff09;复制新建的 Gitee 仓库地址&am…

Unity3D之TextMeshPro使用

文章目录 1. TextMeshPro简介2. TextMeshPro创建3. TextMeshPro脚本中调用4. TextMeshPro字体设置及中文支持过程中出现的一些问题 1. TextMeshPro简介 【官网文档】https://docs.unity.cn/cn/2020.3/Manual/com.unity.textmeshpro.html TextMeshPro 是 Unity 的最终文本解决…

软件测试---Linux

Linux命令使用&#xff1a;为了将来工作中与服务器设备进行交互而准备的技能&#xff08;远程连接/命令的使用&#xff09;数据库的使用&#xff1a;MySQL&#xff0c;除了查询动作需要重点掌握以外&#xff0c;其他操作了解即可什么是虚拟机 通过虚拟化技术&#xff0c;在电脑…

第九十七周周报

学习时间&#xff1a; 2024.7.20-2024.7.26 学习产出&#xff1a; 这周科研暂时没有进展&#xff0c;因为服务器这周都进不去&#xff0c;周一的时候上周跑的节点还被停了&#xff08;机房太热&#xff09;&#xff0c;然后这周主要在改吉安县小程序的bug&#xff0c;因为要…

刷新当前页面

一, reload 直接刷新页面 window.location.reload(); $router.go(0);相当于按了 F5, 因此缺点也很明显, 体验感不佳, 因为要加载所有页面资源相对较慢, 比较耗时. 二, Vue Router 刷新当前页面 这个时候, 我们通过 $router.push 一个 refresh 路由的形式实现, 具体步骤如下:…

Leetcode49. 字母异位词分组(java实现)

今天我来给大家分享的是leetcode49的解题思路&#xff0c;题目描述如下 如果没有做过leetcode242题目的同学&#xff0c;可以先把它做了&#xff0c;会更好理解异位词的概念。 本道题的大题思路是&#xff1a; 首先遍历strs&#xff0c;然后统计每一个数组元素出现的次数&#…

电商数据精细化运营解决方案(18页PPT)

方案介绍&#xff1a; 电商数据精细化运营解决方案通过全面、深入的数据分析与应用&#xff0c;助力电商企业实现精细化管理和精准化营销&#xff0c;从而在激烈的市场竞争中脱颖而出。 部分方案内容&#xff1a;

Prometheus 监控Tomcat等java应用的状态

5月应用服务出现问题&#xff0c;当别的小伙伴问我&#xff0c;有没有Tomcat等应用状态的监控的时候&#xff0c;我有点儿尴尬。所以赶紧抽空部署一下。 在配置之前&#xff0c;就当已经会安装jdk和tomcat了。 一、下载jmx_exporter #linux下 cd /usr/local/prometheus wget …

Docker入门指南:Linux系统下的完整安装步骤与常见问题解答

本文以centos7演示。 Docker安装 可参考官方安装文档&#xff1a;Install Docker Engine on CentOS | Docker Docs 一图流&#xff1a; # 移除旧版本docker sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logro…

将一个url文件链接下载到本地的方法,以及从url中提取并创建一个文件保存路径,以及m3u8文件的解析及下载

最近工作中&#xff0c;遇到了讲一个m3u8的文件下载到本地&#xff0c;使用代码如下&#xff1a; import urllib.requestm3u8file os.path.join(folderPath, dirName .m3u8) urllib.request.urlretrieve(m3u8url, m3u8file) 不过上述代码有个小问题&#xff0c;就是需要使用…