学习python的第十三天之数据类型——函数传参中的传值和传址问题
学习python的第十三天之数据类型——函数传参中的传值和传址问题
函数传参中的传值和传址问题
函数传参的机制可以理解为传值(pass-by-value)和传址(pass-by-reference)的混合体,但实际上更接近于传对象引用(pass-by-object-reference)。
不可变类型(传值?)
对于不可变类型(如整数、浮点数、字符串、元组等),当你将它们作为参数传递给函数时,似乎是在传值,因为任何在函数内部对这些参数所做的修改都不会影响到函数外部的变量。
def modify_value(x):x = 10 # 解释:相当于将10的地址给到临时变量x,替换了原来5的地址print("Inside function:", x, id(x)) # 解释:所以打印的地址是10的地址a = 5 # 解释:将5的地址给到a
modify_value(a) # 解释:相当于将a的地址给到modify_value函数中的临时变量x
print("Outside function:", a, id(a)) # 解释:a的地址是5的地址# Inside function: 10 2450059455056
# Outside function: 5 2450059454896
# 地址发生变化,因为小整数池的原因
在这个例子中,a 是一个整数对象,当它被传递给 modify_value 函数时,函数内部得到的是 a 的一个副本(在内存中是一个新的整数对象 10),而不是 a 本身。因此,函数内部对 x 的修改不会影响到外部的 a。
然而,这并不是说 Python 在传递这些值时进行了完整的拷贝。实际上,Python 传递的是对不可变对象的引用,但由于这些对象是不可变的,所以你不能通过引用改变它们的内容。当你尝试改变它们时,你实际上是在创建一个新的对象。
可变类型(传址?)
对于可变类型(如列表、字典、集合等),当你将它们作为参数传递给函数时,函数内部可以直接修改这些对象的内容,这种行为看起来像是传址。
def modify_list(lst):lst.append(10) # 解释:因为list列表是可变类型,内容发生变化后地址不会变,所以lst的地址还是传进来的my_list的地址2077876147584print("Inside function:", lst, id(lst)) # 解释:所以打印的地址还是my_list的地址2077876147584,但是内容变换了my_list = [1, 2, 3]
modify_list(my_list) # 解释:相当于将my_list的地址2077876147584给到modify_list函数中的临时变量lst
print("Outside function:", my_list, id(my_list)) # 解释:因为在函数中将地址2077876147584的列表内容进行修改了,但是my_list的地址没变,还是指向2077876147584,所以my_list的内容也跟着变化了# Inside function: [1, 2, 3, 10] 2077876147584
# Outside function: [1, 2, 3, 10] 2077876147584
# 地址没发生变化,因为list列表为可变类型
在这个例子中,my_list 是一个列表对象,当它被传递给 modify_list 函数时,函数内部得到的是对同一个列表对象的引用。因此,函数内部对 lst 的修改会影响到外部的 my_list。
传址和传值的对比解释(重要)
前情提要:如过函数中给入的参数是函数中有的变量,则在这个函数中变量会作为局部变量使用,不会影响到外面同名的变量。
在Python中,当我们提到“对象的地址”或“对象的内存地址”时,我们实际上是在谈论一个更抽象的概念,即对象的标识符。这个标识符是由Python解释器在内部生成的,用于唯一地标识每个对象。虽然标识符在底层实现上可能与对象的实际内存地址有关,但Python解释器并不直接暴露内存地址给开发者。标识符是一个更高级的抽象,它允许Python在内存管理方面保持更大的灵活性。
list1 = ['a', 'b', 'c', [1,3,5]]
list2 = list1[::-1]
list3 = list1[1:-1]print(list1,id(list1)) # 输出: ['a', 'b', 'c', [1, 3, 5]] 2464707002304
print(list2,id(list1)) # 输出: [[1, 3, 5], 'c', 'b', 'a'] 2464707002304
print(list3,id(list1)) # 输出: ['b', 'c'] 2464707002304
print('-----------------------------------')def func1(l1, l2):l1 = l2l2.append(10)func1(list2, list3)
print('-----------------------------------')
print(list1,id(list1)) # 输出: ['a', 'b', 'c', [1, 3, 5]] 2464707002304
print(list2,id(list1)) # 输出: [[1, 3, 5], 'c', 'b', 'a'] 2464707002304
print(list3,id(list1)) # 输出: ['b', 'c', 10] 2464707002304# func1(list2, list3)实际上是将list2的‘身份标识符’给到了函数里的l1,将list3的‘身份标识符’给到了函数里的l2,
# 因为函数中存在l1这个赋值变量,但是为什么l2不算是临时变量呢?
# 是因为l1 = l2这句,通俗的说你要存放一个东西,无论这个东西是什么,你要先有一个位置,
# l1就是这个位置,l2就是这个东西,而l2这个东西的来源就是靠调用func1()这个函数来分配的;
# 同样l2.append(10)这一句,只是对这个未知的l2进行的一步操作,也没有创建一个叫l2的临时变量,
# 综上,函数中的l1是临时变量,所以对l1的赋值操作不会影响到给予‘身份标识符’的list2,
# 但是l2不是临时变量,所以l2指代的就是list3,所以l2的操作就会影响到给予‘身份标识符’的list3。
# 如果函数改为:
list1 = ['a', 'b', 'c', [1,3,5]]
list2 = list1[::-1]
list3 = list1[1:-1]print(list1,id(list1)) # 输出: ['a', 'b', 'c', [1, 3, 5]] 2587051900864
print(list2,id(list1)) # 输出: [[1, 3, 5], 'c', 'b', 'a'] 2587051900864
print(list3,id(list1)) # 输出: ['b', 'c'] 2587051900864
print('-----------------------------------')def func2(l1, l2):l1 = l2l2 = l2[::-1]func2(list2, list3)
print('-----------------------------------')
print(list1,id(list1)) # 输出: ['a', 'b', 'c', [1, 3, 5]] 2587051900864
print(list2,id(list1)) # 输出: [[1, 3, 5], 'c', 'b', 'a'] 2587051900864
print(list3,id(list1)) # 输出: ['b', 'c'] 2587051900864# 可以发现,这次l2就没有影响到list3,因为这次l2也变成了临时变量
# 同理就算l1换成list1,l2换成list2,函数中的list1和list2也只是存在与函数中,和全局的list1、list2不是同一个;
list1 = ['a', 'b', 'c', [1,3,5]]
list2 = list1[::-1]
list3 = list1[1:-1]print(list1,id(list1)) # 输出: ['a', 'b', 'c', [1, 3, 5]] 2221755744192
print(list2,id(list1)) # 输出: [[1, 3, 5], 'c', 'b', 'a'] 2221755744192
print(list3,id(list1)) # 输出: ['b', 'c'] 2221755744192
print('-----------------------------------')def func2(list1, list2):list1 = list2list2.pop()func2(list2, list3)
print('-----------------------------------')
print(list1,id(list1)) # 输出: ['a', 'b', 'c', [1, 3, 5]] 2221755744192
print(list2,id(list1)) # 输出: [[1, 3, 5], 'c', 'b', 'a'] 2221755744192
print(list3,id(list1)) # 输出: ['b'] 2221755744192# 结果就是函数中的list1临时变量既没有影响到全局同名的list1,也没有影响到给予‘身份标识符’的list2;
# 函数中的list2(非临时变量),只影响到给予‘身份标识符’的list3,而没有影响到全局同名的list2;
总结
更准确地说,Python 在函数传参时传递的是对对象的引用。对于不可变对象,由于你不能改变它们的内容,所以这种传递方式看起来像是传值。对于可变对象,由于你可以改变它们的内容,所以这种传递方式看起来像是传址。
相关文章:
学习python的第十三天之数据类型——函数传参中的传值和传址问题
学习python的第十三天之数据类型——函数传参中的传值和传址问题 函数传参中的传值和传址问题 函数传参的机制可以理解为传值(pass-by-value)和传址(pass-by-reference)的混合体,但实际上更接近于传对象引用ÿ…...
Windows11深度学习环境配置
CUDA、CUDNN 一、安装另一个版本的CUDA 下载.exe文件,网址打不开自己开热点就能解决:CUDA Toolkit 11.2 Downloads | NVIDIA Developer 若遇到“You already have a newer version of the NVIDIA Frameview SDK installed” 1.把电脑已经存在的FrameVi…...
电销老是被标记,该如何解决!!!
在当今的商业世界中,电话销售依然是许多企业拓展业务、接触客户的重要手段。然而,电销人员常常面临一个令人头疼的问题 —— 老是被标记。 一、电销被标记的困扰 当你的电话号码被频繁标记为 “骚扰电话”“推销电话” 等,会带来一系列不良…...
MyBatis入门——基本的增删改查
目录 一、MyBatis简介 二、搭建MyBatis (一)配置依赖 (二)log4j日志功能 (三)数据库配置文件——jdbc.properties (四)创建MyBatis的核心配置文件 (五)使用MyBatisX插件 三、项目其他配置搭建 (一)创建数据库连接工具类 (二)创建表 (三)创建数据库的实体类 (四)Use…...
学习Gentoo系统中二进制软件包和源代码包的概念
Gentoo Linux 是一个以源代码包管理和高度定制化特性著称的Linux发行版。以下是关于Gentoo系统中二进制软件包和源代码包的概念、发展历程以及它们各自的优势: 二进制软件包概念及发展历程: 概念:Gentoo的二进制软件包是指预先编译好的软件包…...
麦肯锡报告 | 未来的经济引擎:解读下一代竞争领域
随着科技和商业的快速发展,一些具有高增长性和高动态性的行业正在悄然崛起,成为推动全球经济发展的新引擎。这些行业被称为“竞争领域”(Arenas)。据麦肯锡全球研究院(MGI)的研究,这些领域有望在…...
连接mysql并读取指定表单数据到DataFrame
提问 python 如何连接mysql并读取指定表单数据到DataFrame 解答 要在Python中连接MySQL并读取指定表单数据到DataFrame,你可以使用pandas库结合sqlalchemy引擎或者mysql-connector-python。这里我将展示两种方法的示例代码。 使用pandas和sqlalchemy 确保安装了…...
从入门到精通数据结构----四大排序(上)
目录 首言: 1. 插入排序 1.1 直接插入排序 1.2 希尔排序 2. 选择排序 2.1 直接选择排序 2.2 堆排序 3. 交换排序 3.1 冒泡排序 3.2 快排 结尾: 首言: 本篇文章主要介绍常见的四大排序:交换排序、选择排序、插入排序、归并排…...
【bug】使用transformers训练二分类任务时,训练损失异常大
使用transformers训练二分类任务时,训练损失异常大 问题分析 问题 training_loss异常大,在二分类损失中,收敛在1~2附近,而eval_loss却正常(小于0.5) 分析 参考: Bug in gradient accumulation…...
文献阅读与笔记整理技巧
文献阅读 1.原因 (1)了解背景知识(硕博学位论文,大牛文献综述) (2)把握研究方向(行业最新论文,大牛文献综述) (3)学习设计思路&am…...
Python Flask中集成SQLAlchemy和Flask-Login
在现代Web应用开发中,数据库和用户认证是两个非常重要的功能。Flask作为一个轻量级的Python Web框架,本身只提供了最基本的Web功能。但是,它可以通过集成各种优秀的扩展库来增强功能。本文将介绍如何在Flask应用中集成SQLAlchemy(数据库)和Flask-Login(用户认证),并提供一个完整…...
esp32 JTAG 串口 bootload升级
文章目录 一、前言二、了解 JTAG 和 Ymodem 的工作原理2.1 环境准备2.2 Ymodem 协议工作原理2.3 固件分区准备 三、关键升级函数五、使用shell 测试 一、前言 如果使用 JTAG 串口 结合 Ymodem 协议 实现 ESP32 的固件升级,整体逻辑将围绕通过串口传输固件文件并将其…...
【linux】(17)压缩和解压
tar tar 是一个用于创建、维护、修改和解压缩存档文件的 Linux 命令。tar 常常用于备份文件或者将多个文件打包成一个文件以便于传输或存储。以下是 tar 命令的详细教程,包括常用选项和示例: 基本语法 tar [选项] [文件或目录]常用选项 -c࿱…...
摄像机视频分析软件下载LiteAIServer视频智能分析平台玩手机打电话检测算法技术的实现
随着科技的不断进步,摄像机视频分析软件的发展已经为我们的生活带来了许多便捷。其中,LiteAIServer视频智能分析平台的玩手机打电话检测算法技术尤为突出,它利用先进的图像处理和人工智能技术,能够自动识别并监控视频中的玩手机或…...
springboot购物推荐网站的设计与实现(代码+数据库+LW)
摘要 随着信息互联网购物的飞速发展,一般企业都去创建属于自己的电商平台以及购物管理系统。本文介绍了东大每日推购物推荐网站的开发全过程。通过分析企业对于东大每日推购物推荐网站的需求,创建了一个计算机管理东大每日推购物推荐网站的方案。文章介…...
【Unity3D插件】Unity3D HDRP Outline高亮发光轮廓描边插件教程
推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享QQ群:398291828小红书小破站 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 最近用Unity3D的HDRP(高清渲染管…...
QT基础 UI编辑器 QT5.12.3环境 C++环境
一、UI编辑器 注意:创建工程时,要勾上界面按钮 UI设计师界面的模块 UI编辑器会在项目构建目录中自动生成一个ui_xxx.h(构建一次才能生成代码),来表示ui编辑器界面的代码,属于自动生成的,一定不…...
计算机网络socket编程(5)_TCP网络编程实现echo_server
个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 计算机网络socket编程(5)_TCP网络编程实现echo_server 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记,欢迎大家在评论区交…...
go语言闭包捕获的是变量的引用而不是变量的值
在 Go 语言中,闭包捕获的是变量的引用,而不是变量的值。这意味着闭包会引用循环变量或外部变量的实际内存位置,而不是在闭包创建时复制变量的值。这种行为有时会导致意外的结果,尤其是在循环中创建多个闭包时。 闭包捕获变量的引…...
周期法频率计的设计
目录 周期法频率计 分析: 设计过程: 周期法频率计 对于低频信号,应用周期法进行测频。周期法测频的基本原理是:应用标准频率信号统计被测信号两个相邻脉冲之间的脉冲数,然后通过脉冲数计算出被测信号的周期ÿ…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...
