当前位置: 首页 > news >正文

学习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)的混合体,但实际上更接近于传对象引用&#xff…...

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&#xff1…...

摄像机视频分析软件下载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 语言中,闭包捕获的是变量的引用,而不是变量的值。这意味着闭包会引用循环变量或外部变量的实际内存位置,而不是在闭包创建时复制变量的值。这种行为有时会导致意外的结果,尤其是在循环中创建多个闭包时。 闭包捕获变量的引…...

周期法频率计的设计

目录 周期法频率计 分析: 设计过程: 周期法频率计 对于低频信号,应用周期法进行测频。周期法测频的基本原理是:应用标准频率信号统计被测信号两个相邻脉冲之间的脉冲数,然后通过脉冲数计算出被测信号的周期&#xff…...

嵌入式轻量级任务调度框架cola_os解析与实践

1. 嵌入式轻量级任务调度框架cola_os深度解析在嵌入式开发中,我们经常面临一个经典困境:对于功能简单、实时性要求不高的多任务场景,使用完整的RTOS显得过于臃肿,而裸机轮询又难以维护。今天要介绍的cola_os正是为解决这个问题而生…...

【二进制指数退避算法】

二进制指数退避算法一、概念二、原理一、概念 1.二进制指数退避算法是以太网退避算法,是 CSMA/CD 里处理冲突后重发的核心规则。 2.发生冲突后,不立刻重发,而是随机等一段时间再试。 3.冲突次数越多,随机等待的范围就越大&#x…...

P3916 图的遍历 题解(反向建图)

更好的阅读体验(博客园) 题面 P3916 图的遍历 题目描述 给出 NNN 个点,MMM 条边的有向图,对于每个点 vvv,令 A(v)A(v)A(v) 表示从点 vvv 出发,能到达的编号最大的点。现在请求出 A(1),A(2),…,A(N)A(1),…...

StructBERT WebUI效果实测:渐变紫界面+实时健康监控+高亮等级标签全展示

StructBERT WebUI效果实测:渐变紫界面实时健康监控高亮等级标签全展示 1. 工具概述 StructBERT文本相似度-中文-通用-WebUI是一个基于百度StructBERT大模型实现的高精度中文句子相似度计算工具。这个工具能够准确判断两个中文句子在语义上的相似程度,为…...

别再只盯着细胞比例了!用Xenium数据做小鼠肺腺癌空间邻域分析,手把手教你找到真正的肿瘤边界

空间邻域分析:重新定义肿瘤微环境的生物学边界 在单细胞和空间组学研究中,我们常常陷入一个思维定式——过度关注细胞类型的比例变化,却忽略了细胞在三维空间中的精妙排布所蕴含的关键信息。这种比例优先的思维模式,就像试图通过统…...

AT命令驱动的跨平台嵌入式Web服务器框架

1. 项目概述ESP8266_AT_WebServer 是一个面向嵌入式硬件工程师的轻量级、跨平台 Web 服务框架,其核心设计哲学是“硬件无关性”与“协议抽象化”。它并非直接运行于 ESP8266/ESP32 芯片之上,而是将这些 Wi-Fi 模块降级为一个标准的 AT 命令外设&#xff…...

企业开始用 AI 后,最容易被忽略的其实是这件事!

这两年,越来越多企业开始尝试把 AI 用到日常办公中。从写邮件、整理纪要,到查询知识库、生成文档,AI 正在从个人工具变成企业工作的一部分。但很多企业在推进 AI 时,首先关注的往往是功能和效率,比如“能不能写”“能不…...

5G RedCap路由器如何选?关键特性解析与典型应用场景指南

1. 5G RedCap路由器选购的核心指标 第一次接触5G RedCap路由器时,我被参数表里密密麻麻的术语搞得头晕眼花。后来在工业现场实测了7款不同型号后,才发现真正影响使用体验的关键指标其实就这几个: 频段支持就像路由器的"语言能力"。…...

Anthropic:AI 编程从单打独斗到团队协作的生产关系升级

【导语:在 AI 时代,编程不再是少数人的特权。Anthropic 让 Claude 独自完成项目,从单智能体到多智能体结构,实现了从生成代码到交付成果的跨越,带来了生产关系的升级。】Claude 单枪匹马难交付,多智能体团队…...

Nunchaku FLUX.1 CustomV3问题解决:提示词怎么写?参数怎么调?一篇搞定

Nunchaku FLUX.1 CustomV3问题解决:提示词怎么写?参数怎么调?一篇搞定 你是不是也遇到过这种情况:兴冲冲地打开了Nunchaku FLUX.1 CustomV3,想生成一张美美的吉卜力风格插画,结果出来的图片要么“货不对板…...