Python 变量?对象?引用?赋值?一个例子解释清楚

哈喽大家好,我是咸鱼。

前天有个小伙伴找到我,给了我一段 python 代码:

a = [1, 2]
a[1] = a
print(a[1])

然后问我为什么结果是 [1, [...]],我一看这个问题有意思,我说三言两语解释不清楚,我写篇文章到时候你看下吧,于是有了今天这篇文章。

在正式开始之前,让我们先弄清楚一些概念。

对象?变量?引用?赋值?

“Python 中一切皆对象”,相信这句话大家在学习 Python 的时候都已经听的耳朵起茧子了吧。

在 Python 中,所有的数据都是对象,包括基本数据类型(例如整数、浮点数、字符串等)以及用户自定义的类型(类的实例等)。

对象其实是内存中分配的一块空间,用来存储其值。每个对象都有一个唯一的标识符(id),可以通过 id() 函数获取

不但如此,每一个对象都具有两个标准的头部信息:

  • 类型标志符(Type Identifier): 每个对象都有一个类型信息,可以通过 type() 函数获取。
  • 引用计数器(Reference Counter): 引用计数器表示有多少个引用指向该对象,当引用计数降为零时,对象会被垃圾回收。( Python 也使用其他垃圾回收机制,例如循环垃圾回收器来处理引用环的情况。)

在 Python 中,变量实际上是对象的【引用】,而不是对象本身的【存储】。当我们执行赋值语句时,会自动建立变量和对象之间的关系,即引用。

变量就像是一个指针,【指向】内存中存储对象的位置。

我们来看一个例子:

a = 1
b = a
a = a + 1

首先将 1 赋值于 a,即 a 指向了 1 这个对象。

接着 b = a 则表示让变量 b 也同时指向 1 这个对象。Python 的对象可以被多个变量所指向(引用)。


最后执行 a = a + 1,在这里需要注意的是,Python 的基础数据类型(例如整型(int)、字符串(string)等)是不可变的

所以,a = a + 1,并不是让 a 的值增加 1,而是表示重新创建了一个新的值为 2 的对象,并让 a 指向它。但是 b 仍然不变,仍然指向 1 这个对象。

因此最后的结果是,a 的值变成了 2,而 b的值不变仍然是 1

通过这个例子你可以看到,这里的 ab,开始只是两个指向同一个对象的变量而已,或者你也可以把它们想象成同一个对象的两个名字。

简单的赋值 b = a,并不表示重新创建了新对象,只是让同一个对象被多个变量指向或引用。

为什么?

在了解了变量、对象、引用、赋值之后,我们回到一开始的例子。

a = [1, 2]
a[1] = a
print(a[1])

这段代码中创建了一个列表 a,其中包含两个元素(1 和 2),然后 a[1] 被赋值为整个列表 aa[1] = a),当你打印 a[1] 时,它实际上是指向列表 a 本身。

a = [1, <reference to a>]

这样就会导致循环引用的问题。

我们来分步骤解释一下这个过程:

  • a 是一个包含两个元素的列表:[1, 2]
  • a[1] = a 将列表 a 的第二个元素设为 a,即a[1]实际上指向列表 a 本身,形成了一个循环引用
  • 当打印 a[1] 时,Python 发现这是一个特殊的情况,即这个元素是对列表本身的引用。为了避免无限循环,Python 会显示 ...,表示引用已经进入了一个循环。因此看到的结果是 [1, [...]]

那如何避免循环引用呢?可以使用浅拷贝或者深拷贝来解决。

我们用浅拷贝来试一下:

import copya = [1, 2]
a[1] = copy.copy(a)
print(a[1])# 结果是[1,2]

浅拷贝创建一个新的对象,然后将原始对象中的元素复制到新对象中。但是,如果原始对象的元素是可变对象(例如列表),那么浅拷贝只会复制对象的引用而不是对象本身。

就比如上面的例子:

  • a = [1, 2] 创建了一个列表 a,其中有两个元素 1 和 2。
  • a[1] = copy.copy(a) 将列表 a 的第二个元素修改为对列表 a 的浅拷贝。
  • 打印 a[1],此时 a[1] 指向了新的对象 [1, 2]

关于浅拷贝深拷贝的内容咸鱼后期再写篇文章介绍一下!

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

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

相关文章

和硕拿下AI Pin代工大单公司 | 百能云芯

和硕公司近日成功中标AI Pin代工大单&#xff0c;AI Pin被认为是继iPhone之后的下一个划时代产品&#xff0c;吸引了全球科技圈的广泛关注。和硕公司对此表示&#xff0c;他们不会只专注于单一客户&#xff0c;而是期望在下半年有更多新品上市&#xff0c;为公司带来丰硕的业绩…

C++ -- 入门(引用)

1.引用 1.1引用的概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 比如&#xff1a;李逵&#xff0c;在家称为"铁牛"&#xff0c;江湖上人称&q…

CC工具箱使用指南:【平差工具】

一、简介 平差是一个摘自英文单词“adiustment”的中文翻译&#xff0c;它最初源于土地测量工程&#xff0c;并在后来广泛应用于各个测量领域在传统的测量中&#xff0c;由于各种误差的存在&#xff0c;例如仪器、人为、大地形态等因素&#xff0c;所得到的测量结果是不完全准…

MySQL基础(一)

学习数据库的目的&#xff1a; 实现数据持久化到本地。使用完整的管理系统统一管理&#xff0c;可以实现结构化查询&#xff0c;方便管理。 一、数据库概述 数据库&#xff08;DataBase&#xff09; 为了方便数据的存储和管理&#xff0c;它将数据按照特定的 规则存储在磁盘…

项目解决方案: 视频融合(实时监控视频和三维建模进行融合)设计方案

目 录 一、需求描述 1、视频接入和控制要求 2、视频播放需求 3、提供其他应用的调用 二、方案设计 &#xff08;一&#xff09;系统设计图 &#xff08;二&#xff09;产品实现方案 三、产品和功能描述 &#xff08;一&#xff09;总体描述 &#xf…

Java 数据结构集合

文章目录 Java 数据结构1. 基本数据结构1.1 数组 (Array)1.2 链表 (Linked List)1.3 栈 (Stack)1.4 队列 (Queue)双向队列优先级队列 2. 树形数据结构2.1 二叉树 (Binary Tree)2.2 堆 (Heap) 3. 散列数据结构3.1 哈希表 (Hash Map)3.2 LinkedHashMap3.3 TreeMapConcurrentHashM…

【C++练级之路】【Lv.7】【STL】vector类的模拟实现

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《C语言》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、成员变量二、默认成员函数2.1 constructor2.2 destructor2.3 copy constructor2.4 operator 三、迭代器…

Java毕业设计-基于jsp+servlet的学生推荐平台管理系统-第81期

获取源码资料&#xff0c;请移步从戎源码网&#xff1a;从戎源码网_专业的计算机毕业设计网站 项目介绍 基于jspservlet的学生推荐平台管理系统&#xff1a;前端 jsp、jquery&#xff0c;后端 servlet、jdbc&#xff0c;集成用户端和管理后台&#xff0c;用户端浏览书籍课程&…

Web06--JavaScript基础02

1、JS流程控制语句 JS与Java一样&#xff0c;也有三个流程控制语句&#xff1a; 顺序结构 选择结构 循环结构 1.1 选择结构 1.1.1 if结构 <script type"text/javascript">if (条件表达式) {代码块;} else if(条件表达式){代码块;} else {代码块;} </scr…

选择排序 | 冒泡排序 | C语言(详解)

一&#xff0c;选择排序 1&#xff0c;基本知识 对排序的双层 for 循环的理解&#xff1a;外层 控制趟数&#xff0c;里层 不断地对数组进行遍历。 2&#xff0c;逐层深入 经典的选择排序GIF动图&#xff0c;如下&#xff1a; 关键部分&#xff1a; Ⅰ&#xff0c;从数组中…

mathematical-expression 实现 数学表达式解析 Java 篇

mathematical-expression 实现 数学表达式解析 Java 篇 Java技术栏 使用 ME&#xff08; mathematical-expression&#xff09;数学表达式解析库 实现Java中 数学表达式 的解析和计算。 目录 文章目录 mathematical-expression 实现 数学表达式解析 Java 篇目录mathematical-…

面试知识点:notify是随机唤醒线程吗(唤醒线程顺序)?

做 Java 开发的小伙伴&#xff0c;对 wait 方法和 notify 方法应该都比较熟悉&#xff0c;这两个方法在线程通讯中使用的频率非常高&#xff0c;但对于 notify 方法的唤醒顺序&#xff0c;有很多小伙伴的理解都是错误的&#xff0c;有很多人会认为 notify 是随机唤醒的&#xf…

构建中国人自己的私人GPT—与文档对话

先看效果 他可以从上传的文件中提取内容作为答案。上传文件摄取速度 摄取速度取决于您正在摄取的文档数量以及每个文档的大小。为了加快摄取速度&#xff0c;您可以在配置中更改摄取模式。 存在以下摄取模式&#xff1a; simple&#xff1a;历史行为&#xff0c;一次按顺序摄…

超实用桌面助手!时间、日期、天气,一目了然!完全免费!

文章目录 &#x1f4d6; 介绍 &#x1f4d6;&#x1f3e1; 环境 &#x1f3e1;&#x1f4d2; 使用方法 &#x1f4d2;⚓️ 相关链接 ⚓️ &#x1f4d6; 介绍 &#x1f4d6; 这是一款我根据自己的需求写的一个桌面小工具&#xff0c;自己一直在用&#xff0c;现在分享给需要的朋…

纯前端实现了Excel文件转JSON和JSON转Excel下载

需求前提&#xff1a; 上传Excel文件&#xff0c;并将Excel文件的内容拿出来转换为JSON本地定义JSON数据&#xff0c;然后将它封装后转换为Excel文件下载 安装依赖 这两个功能是借助xlsx包实现的&#xff0c;所以需要先安装xlsx包&#xff1a; npm install xlxs依赖引用 i…

【Android Gradle 插件】Gradle 基础配置 ④ ( Gradle Wrapper 配置作用 | Gradle 下载的依赖库存放位置 )

一、Gradle Wrapper 配置作用 gradle wrapperdistributionBaseGRADLE_USER_HOME distributionPathwrapper/dists distributionUrlhttps\://services.gradle.org/distributions/gradle-6.7.1-bin.zip zipStoreBaseGRADLE_USER_HOME zipStorePathwrapper/distsGradle Wrapper 配…

【云原生】Docker的安装和镜像操作

目录 什么是Docker&#xff1f; 容器化越来越受欢迎&#xff0c;因为容器是&#xff1a; Docker与虚拟机的区别&#xff1a; 容器在内核中支持2种重要技术&#xff1a; Docker核心概念&#xff1a; 安装Docker 安装依赖包 设置阿里云镜像源 安装 Docker-CE并设置为开机…

C++设计模式之迭代器模式

【声明】本题目来源于卡码网&#xff08;https://kamacoder.com/&#xff09; 【提示&#xff1a;如果不想看文字介绍&#xff0c;可以直接跳转到C编码部分】 【设计模式大纲】 【简介】 --什么是迭代器模式&#xff08;第19种设计模式&#xff09; 迭代器模式是⼀种行为设计模…

docker-compose搭建redis集群

这里用docker-compose在一台机器搭建三主三从&#xff0c;生产环境肯定是在多台机器搭建&#xff0c;否则一旦这台宿主机挂了&#xff0c;redis集群全挂了&#xff0c;依然是单点故障。同时&#xff0c;受机器性能极限影响&#xff0c;其并发也上不去&#xff0c;算不上高并发。…

web开发学习笔记(14.mybatis基于xml配置)

1.基本介绍 2.基本使用 在mapper中定义 在xml中定义&#xff0c;id为方法名&#xff0c;resultType为实体类的路径 在测试类中写 3. 动态sql&#xff0c;if和where关键字 动态sql添加<where>关键字可以自动产生where和过滤and或者or关键字 where关键字可以动态生成whe…