一文读懂 Python 值传递和引用传递

Python值传递和引用传递(详细分析) 目录 1. 形参与实参 2. Python的数据类型 3.Python变量及其赋值 3.1 不可变对象赋值 3.2 可变对象赋值 3.3 变量删除 3.4 变量赋值总结 4.Python函数的参数传递 4.1 参数传递定义 4.2 不可变对象的参数传递 4.3 可变对象的参数传递 5.总结 6 不可变与可变对象赋值对比: 6.1 单层源对象 6.1.1 源对象是不可变数据类型(对象元素也不可变) 6.1.2 源对象是可变数据类型(对象元素也不可变的情况下) 6.2 多层 阅读详情

版本

  • Python 3.9

前言

  • 在编程语言中,值传递(pass by value)和引用传递(pass by reference)是两个重要的概念。它们涉及到变量在函数调用中的传递方式,对于理解函数调用和参数传递的机制至关重要。在本文中,我们将深入探讨 Python 中的值传递和引用传递,并通过代码示例进行说明。

形参和实参

  • 我们先了解一点前置知识,形参和实参,先说概念:形参出现在函数定义中,在整个函数体内都可使用,离开函数体则不可使用。实参出现在主调函数中,进入被调函数后,不能使用。
python
复制代码
def func(param):
    # 这里 param 为形参
    print(param)


if __name__ == "__main__":
    # 这里的 a 就是实参
    a = 1
    func(a)

值传递和引用传递

  • 我们先了解一下值传递和引用传递的概念:值传递是指在调用方式时,将实参的值拷贝一份给形参,对形参的修改不影响实参。引用传递也叫地址传递,指在调用方法时将实参的地址传递给形参,对形参的修改将影响实参的值,即传递的是实参的内存地址。

Python 变量存储

  • 对于python而言,python的一切变量都是对象,变量的存储采用了引用语义的方式,存储的只是一个变量的值所在的内存地址,而不是这个变量的只本身。

Python 变量存储

  • 代码实测:
python
复制代码
a = 1
print(f"变量a的地址:{id(a)}")

b = 1
print(f"变量b的地址:{id(b)}")

b = 2
print(f"变量b的地址:{id(b)}")
  • 上面实例输出如下:
text
复制代码
变量a的地址:2483649669424
变量b的地址:2483649669424
变量b的地址:2483649669456
  • 从实际用例我们可以看出,a、b = 1 时,这里底层为了性能考虑指向相同的内存,当 b 发生改变时,发生写时复制,b 指向了新的内存地址。

值语义和引用语义

值语义

  • 值语义是指将变量赋值为另一个变量时,会复制变量的值,而不是引用原始值所在的内存地址。如 Java 的基本数据类型。

引用语义

  • 引用语义是指将变量赋值为另一个变量时,实际上是将变量指向同一个对象的内存地址,而不是复制对象的值。如 Java 的引用数据类型、Python 值存储。

探讨 Python 值传递和引用传递

  • 了解完上面的一些基本概念后,我们从可变(mutable)和不可变(immutable)两种类型来探讨 Python 值传递和引用传递:

不可变(immutable)类型

  • 不可变变量的值一旦创建,就不能被修改。如果你尝试修改一个不可变对象的值,Python 将会创建一个新的对象。Python 中的不可变对象包括整数(int)、浮点数(float)、字符串(str)、元组(tuple)等。
  • 先简单看一个下面的例子:
python
复制代码
def modify_value(x):
    print(f"变量x修改前地址:{id(x)}")
    x = x + 10
    print(f"变量x修改后地址:{id(x)}")
    print("函数内部修改后的值为:", x)


# 调用函数
value = 5
print(f"变量value地址:{id(value)}")
modify_value(value)
print("函数外部原始值为:", value)
  • 在这个示例中,我们定义了一个函数 modify_value,它接受一个参数 x。在函数内部,我们对 x 的值进行修改,并打印出修改后的值。然后我们调用函数,传递了一个值为 5 的参数 value。运行以上代码,将会输出:
text
复制代码
变量value地址:1886976960944
变量x修改前地址:1886976960944
变量x修改后地址:1886976961264
函数内部修改后的值为: 15
函数外部原始值为: 5
  • 可以看到,尽管在函数内部修改了形式参数 x 的值,但并没有影响到函数外部实际参数 value 的值,而发生了写时复制。

可变(mutable)类型

  • 可变变量的值可以在原地修改,而不会创建一个新的对象。Python 中的可变对象包括列表(list)、字典(dict)、集合(set)等。
  • 我们以 list 类型为例:

案例一

python
复制代码
def modify_list(list):
    print(f"变量list地址:{id(list)}")
    list[2] = 4
    print(f"变量list修改地址:{id(list)}")
    print("函数内部修改后的列表为:", list)


# 调用函数
my_list = [1, 2, 3]
print(f"变量my_list地址:{id(my_list)}")
modify_list(my_list)
print("函数外部原始列表为:", my_list)
  • 输出如下:
text
复制代码
变量my_list地址:2115249727936
变量list地址:2115249727936
变量list修改地址:2115249727936
函数内部修改后的列表为: [1, 2, 4]
函数外部原始列表为: [1, 2, 4]

案例二

python
复制代码
def modify_list(list):
    print(f"变量list地址:{id(list)}")
    list = [6, 6, 6]
    print(f"变量list修改地址:{id(list)}")
    print("函数内部修改后的列表为:", list)


# 调用函数
my_list = [1, 2, 3]
print(f"变量my_list地址:{id(my_list)}")
modify_list(my_list)
print("函数外部原始列表为:", my_list)
  • 输出如下:
text
复制代码
变量my_list地址:2141908331136
变量list地址:2141908331136
变量list修改地址:2141908181248
函数内部修改后的列表为: [6, 6, 6]
函数外部原始列表为: [1, 2, 3]
  • 看完上面的两个案例你是否有些许疑惑,案例一修改了函数外的原始值,案例二未修改函数外的原始值,下面我们用图解来解释一下上面发生了什么:

案例一转存失败,建议直接上传图片文件

案例二

  • 从图解中我们可以清晰的看到,在案例一和案例二中函数传递了 my_list 地址的拷贝值,案例一中持有数组的内存地址,因此成功修改了原数组元素,案例二中 list 的内存地址修改为新的数组内存地址,并没有修改原数组的值。
  • 通过对可变(mutable)和不可变(immutable)两种类型的函数传递的分析,我们可以知道由于 Python 中一切皆对象的特性,实际传递给函数的都是内存地址的拷贝,从表现上来说,我们可以说 Python 中都是值传递,了解过 Java 的同学会发现这里和 Java 的引用类型原理一致。

拓展:不可变类型真的不可变?

  • 上面我们提到了可变类型和不可变类型,不可变类型真的是不可变的?我们来看下面的案例:
python
复制代码
arr = (1, 2, [4, 4])

print(f"元组修改前:{arr}")
arr[2][0] = 2
print(f"元组修改后:{arr}")
  • 输出结果:
text
复制代码
元组修改前:(1, 2, [4, 4])
元组修改后:(1, 2, [2, 4])
  • 上面的案例中不可变类型出现了变化,这个是 bug ? 其实并不是,不可变类型的不可变指的是组成的元素是不可变的,在上面的案例 arr 元组中存储的是对应的内存地址,而不可变指的是内存地址和指向无法改变,但如果内存地址指向的是可变类型,比如数组,那么元素内部是可变的。

总结

  • 本文以值传递、引用传递的基本概念、以及 Python 变量存储为基础,从可变(mutable)和不可变(immutable)两种类型来分析 Python 值传递和引用传递的真相,通过充足的案例分析我们发现,Python变量 和 Java 引用类型类似,只存在值传递。

这里给大家分享一份Python全套学习资料,包括学习路线、软件、源码、视频、面试题等等,都是我自己学习时整理的,希望可以对正在学习或者想要学习Python的朋友有帮助!

优快云大礼包:全网最全《全套Python学习资料》免费分享🎁

😝有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

👉优快云大礼包🎁:全网最全《Python学习资料》免费分享(安全链接,放心点击)👈

​

1️⃣零基础入门

① 学习路线

对于从来没有接触过Python的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
在这里插入图片描述

② 路线对应学习视频

还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~在这里插入图片描述

③练习题

每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈!
在这里插入图片描述
因篇幅有限,仅展示部分资料

2️⃣国内外Python书籍、文档

① 文档和书籍资料

在这里插入图片描述

3️⃣Python工具包+项目源码合集

①Python工具包

学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦!
在这里插入图片描述

②Python实战案例

光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿!
在这里插入图片描述

③Python小游戏源码

如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味!
在这里插入图片描述

4️⃣Python面试题

我们学会了Python之后,有了技能就可以出去找工作啦!下面这些面试题是都来自阿里、腾讯、字节等一线互联网大厂,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
在这里插入图片描述
在这里插入图片描述

5️⃣Python兼职渠道

而且学会Python以后,还可以在各大兼职平台接单赚钱,各种兼职渠道+兼职注意事项+如何和客户沟通,我都整理成文档了。
在这里插入图片描述
在这里插入图片描述
上述所有资料 ⚡️ ,朋友们如果有需要 📦《全套Python学习资料》的,可以扫描下方二维码免费领取 🆓
😝有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

👉优快云大礼包🎁:全网最全《Python学习资料》免费分享(安全链接,放心点击)👈

​

Python 引用 从懵懂到精通!!! 阅读详情

相关推荐

Python函数专题:引用传参

在Python中,函数的参数传递机制是一个复杂但重要的主题。理解引用传参的概念以及它在处理可变和不可变对象时的表现,对于编写高效且易于维护的代码至关重要。通过掌握不同类型的参数以及它们的特性,我们可以更灵活地设计函数,提升代码的可读性和可维护性。本文详细介绍了引用传参的基本概念、实现方式、特性以及参数类型。希望读者能够通过这些内容加深对Python函数参数传递机制的理解,并在实际开发中灵活应用。

weixin_71228606的博客 1813

Python之引用

例如,当程序创建一个长度为1的字符串对象s时,Python的解释器会先检查对象池中是否已经存在一个值为s的字符串对象,如果存在,则直接返回该对象;例如,如果程序需要使用多个整数1来做计算,那么Python只需要在常量池中检查是否存在整数1的对象,如果已经存在,则直接引用这个对象,而不是创建新的整数1对象。这可以减少内存的使用,并加速程序的执行。需要注意的是,对于一些简单的对象,如整数、浮点数、字符串等等,如果它们的值相同,它们的地址也可能相同,这是因为Python的常量池机制会共享一些简单对象的内存地址。

qq_63215420的博客 4281

MS1030超声波流量计电路实战:如何用15ps精度优化水表设计(附配置代码)

本文深入探讨了如何利用MS1030超声波流量计芯片实现15ps高精度测量,以优化水表设计。文章从系统误差分配出发,详细解析了硬件电路设计要点、SPI通信配置及核心优化技巧,如利用可编程偏置电压和8回波累加功能来提升抗干扰能力与测量稳定性,并附有实用的配置代码示例。

svm4gardener的博客 332

python中的引用

C++中的指针和引用 ,可以参考博客 https://www.cnblogs.com/heyonggang/archive/2012/12/13/2815730.html 问题导入? 如果你使⽤Python声明了⼀个变量并同时为其赋值,即a = 20,你是否将这条语句简单理解为:1. 计算机开辟了⼀块地址别名为a的内存;2. 往这块内存存储了数据20? 如果你对上述问题的回答为是,那么你对诸如“Python是⼀门动态类型语⾔”、“Python效率远不如C语⾔等静态语⾔效率⾼”等说法也⼀定不了.

周周的博客 1万+

告别‘小爱同学’:用ESP32-S3和esp-sr SDK,从零打造一个离线语音助手(含完整代码)

本文详细介绍了如何利用ESP32-S3芯片和esp-sr SDK从零构建一个离线语音助手,涵盖硬件选型、声学设计、SDK配置及低功耗优化等关键步骤。通过实战案例和完整代码,帮助开发者实现自定义唤醒词和命令词,打造低成本、高隐私的本地语音控制解决方案。

weixin_29041195的博客 370

星辰超级智能体TeleClaw桌面版深度体验:央企出品的本地AI生产力助手

中国电信星辰超级智能体TeleClaw桌面版是一款本地化AI生产力助手,主打数据安全、自主高效和深度协同。作为程序员,作者实测其核心功能包括本地数据处理、长期记忆、定时任务和代码开发辅助,特别适合敏感数据处理和日常办公自动化。相比在线AI工具,TeleClaw在数据安全、合规性和自动化能力方面优势明显,但技能生态和响应速度仍有提升空间。总体评价为务实高效的本地AI助手,尤其适合对数据安全有要求的企业用户。

研究中.... 1348

(Python)可变类型&不可变类型;引用传递&值传递;浅拷贝&深拷贝

可以看到修改i的值不会造成数组a的值的修改,而修改j的值会造成数组b的值的修改,这是为什么呢?

Zssss12的博客 895

LiveReload:释放你的F5,实时预览HTML效果

一、liveReload插件开发背景Web前端开发人员在写页面时,如果修改了HTML or CSS,要想看效果通常的做法就是保存代码就得 Alt+Tab,切换到浏览器(当然,我知道很多开发人员是双屏操作不一定需要切换到浏览器),但是一定要F5刷新才能看自己刚写的代码有没有效果,没有效果就再切换到编辑器下修改,然后再切换到浏览器F5刷新看效果,还没有效果,就再继续修改,如此反复。时间久了,前端自动化...

Char_n的博客 2507

1 分钟读懂:Python 参数传递机制

本文讲解了Python参数传递的本质是"赋值传递",与C++的值传递和引用传递不同。Python中变量是对象引用,赋值只是改变变量指向的对象。对于不可变对象(如int、str),函数内修改会创建新对象,不影响原变量;而对于可变对象(如list、dict),修改内容会影响原变量,但赋值新对象则不会。文章通过代码示例和图示详细说明了变量赋值和传递的原理,帮助读者深入理解Python的核心机制。

Balance 514

MCNP 减方差技巧(最全)

MCNP的减方差技巧,核心在于不显著增加计算时间的前提下,通过修改模拟过程来降低结果的统计误差。尤其适用于,这类问题中粒子很难到达探测器区域,直接模拟效率极低栅元重要性是常用的减方差技巧,该方法主要对计算模型的不同区域定义不同的重要性数值。当粒子从重要性低的区域废物重要性高的区域,产生更多粒子,增大统计量;当从重要性高的区域进入重要性低的区域,会进行,增快计算效率。n= 中子,N;光子,P;电子 Exi= 栅元i的重要性I=栅元总数项目IMP卡是必须的,除非使用了WWN卡如果粒子进入0。

chencheng1127的博客 925

【LAMMPS学习】四、运行 LAMMPS(2)命令行选项

本部分解释了在安装可执行文件或下载源代码并构建可执行文件后如何运行 LAMMPS。命令文档页面描述了输入脚本的结构以及它们可以包含的命令。

荷塘阅色 5242

一辆车帮你读懂python函数

2020年 第三期《python全栈测试开发》网络课程于4月中间开班 感兴趣的小伙伴戳此图标QQ联系: 函数的概念: 有一个超市,a要去买西,走一段距离,b去买东西走一段距离,c去买东西也走一段距离,于是就有了公交车,abc都可以搭这一趟公交车去超市买东西,这里的公交车就是函数。函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。 函数的作用: 后面超市所在的位置扩建,有了菜市场、...

kellyred的博客 175

【异常】OpenClaw 上下文溢出问题(100% context used 309.9k/200k`)排查与解决

摘要:OpenClaw 运行出现"100% context used 309.9k/200k"报错,表示上下文窗口超出200k Token限制。解决方法包括:1) 重启服务或新建会话清空缓存;2) 修改配置文件提升context_window值;3) 长期优化如限制历史对话轮数、分批处理长文本。该问题通常由输入过长或多轮对话累积导致,需控制单次输入量在阈值内。

奶爸的编程之路,也就一周冷个三天 3235

Python基础4(函数)

本文详细介绍了Python函数的定义、参数传递机制及多种参数形式。在定义方面,函数以def关键字开头,遵循特定格式和缩进规则。参数传递方面,通过"标签理论"形象解释了不可变对象(如整数)传递时类似值传递,而可变对象(如列表)传递时类似引用传递的现象,但本质上都是传递对象引用。特别指出重新赋值(=)会创建新对象,而原地修改(如append)会影响原对象。参数形式包括:必须参数(按位置匹配)、关键字参数(按名称匹配)和默认参数(需遵循非默认参数在前原则)。最后通过深拷贝示例展示了如何保护原列

qq_56012214的博客 317

终于找到两个稳定好用的Docker镜像加速源,拉取速度提升几十倍!

国内使用Docker经常遇到镜像拉取慢、超时失败的问题🐳 本文分享两个亲测好用的免费镜像加速源⚡ 实测拉取速度从十几分钟缩短到几十秒,稳定性接近100%📊 支持一键配置脚本,支持多平台使用✨

XiaoqiangClub的博客 946

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

10分钟让你看懂python_10分钟学会Python基础知识

今天跟大家分享下Python的相关内容,让你10分钟学会Python基础知识。看完本文大概需要8分钟,看完后,仔细看下代码,函数基本知识就OK了。一、函数基础python入门简单地说,一个函数就是一组Python语句的组合,它们可以在程序中运行一次或多次运行。Python中的函数在其他语言中也叫做过程或子例程,那么这些被包装起来的语句通过一个函数名称来调用。有了函数,我们可以在很大程度上减少复制及...

weixin_39631689的博客 349

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

八股(C++/Python/计网/数据库/操作系统)

自己不会总结,所以就把看过的连接都放进来,以便快速复习。 C++知识 C++所有内容: 【C++ Primer】目录_今岁成蹊的博客-优快云博客_c++primer目录《Effective C++》 目录_KangRoger的博客-优快云博客【C++ Primer】目录_今岁成蹊的博客-优快云博客_c++primer目录 1. 智能指针 【C++学习笔记】37 新特性5:智能指针 - 知乎 (zhihu.com) C++ 智能指针最佳实践&源码分析 2、C++ 中内存分配情况

EquinoxM的博客 1296

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Python工程师面试必备25条Python知识点

1.到底什么是Python?你可以在回答中与其他技术进行对比 下面是一些关键点: Python是一种解释型语言。这就是说,与C语言和C的衍生语言不同,Python代码在运行之前不需要编译。其他解释型语言还包括PHP和Ruby。 Python是动态类型语言,指的是你在声明变量时,不需要说明变量的类型。你可以直接编写类似x=111和x="I'm a string"这样的代码,程序不会报错。 P...

python学习者的博客 2万+

python面试题---第二部分

Python 数据库 网络 算法 其他 Python 1.python参数传递是值传递还是引用传递 都是引用,对于不可改变的数据类型来说,不能改变,如果修改了,事实上是新建一个对象来对待。 2.lambda更简单,省去命名函数名的麻烦 f = lambda x,y:x+y print(f(1, 2)) 3.format可以接受参数不限个数,并且位置可以不按顺序 print(...

冰棒的博客 6637

python - 函数

在许多编程语言中都存在函数,python也不例外。 函数是将单一或者相关联的功能打包的代码段。函数将代码打包,外界只需要调用接口,不必知道其实现过程 函数的意义是代码复用,一次定义多次使用,不仅减轻了代码工作者的作业,而且使得程序的架构更加完善,更改,维护得到提升,扩展性更强(不用类的情况下) python中的函数分为 内置函数 和 用户自定义函数。 内置函数此处不讲,下面我们看看用户自定...

weixin_30432579的博客 105

Self的思考

程序猿在这类中提前在问题过程用方法找到对象位置指针的形参,Python语言约定判断该类存在这个方法后,在这个类的内部定义方法时,首位必添加对象位置指针的形参,称为类初始化。通过self方法打通了类未实例化赋值给对象时,仍然可以在编写代码过程中通过形参方式调用对象的属性,为角度进行编程和便于在类内部的类方法中调用交互的编程状态。电脑分辩数据类型是靠定义值传递的递增方式,对象是由类传递组成的,类是由函数体跟属性组成的,函数是由函数由 返回值、函数名、形参 以及 函数体,四大部分组成。

caidaotenglong的博客 159

零基础转行学Python难度大吗?从哪学起?(附:Python学习路线、资料、视频、实战项目)

零基础学python真的可以吗?

Java_bx的博客 712
上一篇: 深入理解 Python 中的抽象类
下一篇: 手把手教你安装Python,2024最详细的安装教程来了(Pycharm+解释器安装)
Llama-Turbo
博客等级 码龄4年 9901粉丝 2021原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值