python|基础|值传递和引用传递

简介: python|基础|值传递和引用传递

python中,向函数传递参数的类型有两种,一种是值传递,还有一种是引用传递,如果你恰恰好会一点c基础,你可以理解为前者为传递形参,而后者传递指针。本篇文章将探究python的值传递和引用传递。


文本所依赖的python环境为:

image.png


什么是值传递和引用传递


值传递,我们可以理解为传递了一个副本过去,即变量的拷贝,修改副本值不会影响原先的值,例如:

image.png


在上述代码中,我们定义了一个变量x,并赋值为66,而后将x传入其modify_x函数中,在函数中,我们将x赋值为99,打印一下函数中的x值,函数结果。 在主函数中再打印一下x的值。


此结果执行后如下:

image.png


如上代码,我们传入的是形参,在函数中修改形参是不会改变原先的值的,这是因为函数运行时候会先进行压栈,运行过程中会产线局部信息等,恰恰好,我们传入的形参就是该类型的值,所以运行后会出栈,出栈后函数所在的内存也会被销毁,所以函数内的局部变量随着出栈也被销毁了。所以直接修改形参无效。


以上这个就是值传递。


那什么是引用传递呢?我们还是拿上面这个例子做比方,只不过传递的类型换一下,从数值类型更换为字典类型,如:

image.png

如上代码,我们定义了一个字典a,该字典有一个keyx,值为66。在调用modify_x函数中,我们将a传递给了函数,在函数中,我们将该字典keyx的赋值为99,函数结束,在主函数中打印a的值。


执行后结果如下:

image.png

是不是感觉很诧异,同样的代码,为什么传递整形 和 传递 字典 , 所执行的效果不一样呢? 这是因为python机制就是如此,它在传递该值的时候,使用的是指针传递,所以值没有改变,我们将其称之为引用传递。



可以干预参数传递是值传递还是引用传递么?


python不可以干预参数传递的类型,因为python不像cc++一样,可以传递形参,也可以传递指针类型。


python中,参数传递是由解释器实现的,所以说,普通开发者,没办法直接干预参数传递方式,但是可以曲线救国,善用return就是其中一条,例如我们将最开始的代码修改一下,不直接修改值,而是返回一个新的值,例如:

image.png

我们执行后,结果为:

image.png

这并不是修改x的值,而是接收modify_x传递回来的新值。



探寻一下值传递底层是如何实现的


我们之前所述的值传递,都是对数据的拷贝,可是现实真的如此么? 我们可以写一个案例来看下:

image.png


在上述代码中,有一个新的知识点是方法id,它可以查看变量的内存地址。在上述例子中,在主函数中定义一个整形x,值为123,在传递给函数前,使用id方法查看一下变量的内存地址。而后传递给函数modify_x,在该函数中,也使用id方法来查看一下形参x的地址。


若真如我们所猜想,那么2个内存地址应该不一致才对,我们运行下程序:

image.png

发现函数内,和函数外的地址都是一样的? 哎,这是怎么回事呢?


这是因为在python中,解释器为了优化性能,避免大量无用数据拷贝,所以在传递的时候,一开始全是传递的实参,只有当函数内修改了值后,才会新申请一个内存来存该值。细节可以查看这个例子:

image.png

上述代码,我们在modify_x函数中,修改变量x前后都打印其内存地址,结果如下:

image.png

我们发现,在未修改之前,地址内存都是指向同一个地址,修改之后,内存地址也变了。

如果我们将x更换为引用传递的数据的话,就不会出现以下这种情况,可以看下面这个例子:

image.png


上述代码,我们做了一个小小的改动,我们将整形数据x,更改为了列表类型,最后再打印一下x的值,查看变了没有,代码运行结果如下:

image.png

发现内存地址的值并没有改变,且x的值在函数中真的被修改了。


所以通过上述例子,可以说明,值传递的时候,再没有修改的时候,该变量地址还是指向原来的地址,当值被修改后,就会开辟一个新的内存地址用于存储该值。这样的话可以避免拷贝大量数据。

最后再总结一下,哪些类型是引用传递,哪些类型是值传递:


引用传递分别有 列表、字典、集合、自定义类实例等。


值传递分别有 字符串类型、元组、布尔类型、数值类型等。




总结


本篇文章简单介绍了值传递和引用传递,值传递,修改函数内值后,不会影响原始值,而引用传递,修改函数内值后,会印象到原始数据。不过有一个小细节,就是值传递,若不进行修改值的时候,其实内存地址是指向的原始值的地址,当修改值的时候,才会真正申请内存来存储修改的值,但是随着函数出栈,该函数内的数据局部变量,也会被销毁。


相关文章
|
Python
python之函数的参数传递(引用传递和值传递),查看变量的内存地址的方法
python之函数的参数传递(引用传递和值传递),查看变量的内存地址的方法
152 0
|
存储 C++ Python
Python到底是引用传递还是值传递?网上大多数教程都讲错了
或许在很多人的直观印象中,变量是一个容器;给变量赋值,就像是往一个存储的容器中填入一个数据;再次赋值就是把容器中的数据换掉。
|
Python
第115天:Python 到底是值传递还是引用传递
第115天:Python 到底是值传递还是引用传递
174 0
第115天:Python 到底是值传递还是引用传递
|
6月前
|
机器学习/深度学习 存储 设计模式
Python 高级编程与实战:深入理解性能优化与调试技巧
本文深入探讨了Python的性能优化与调试技巧,涵盖profiling、caching、Cython等优化工具,以及pdb、logging、assert等调试方法。通过实战项目,如优化斐波那契数列计算和调试Web应用,帮助读者掌握这些技术,提升编程效率。附有进一步学习资源,助力读者深入学习。
|
3月前
|
Python
Python编程基石:整型、浮点、字符串与布尔值完全解读
本文介绍了Python中的四种基本数据类型:整型(int)、浮点型(float)、字符串(str)和布尔型(bool)。整型表示无大小限制的整数,支持各类运算;浮点型遵循IEEE 754标准,需注意精度问题;字符串是不可变序列,支持多种操作与方法;布尔型仅有True和False两个值,可与其他类型转换。掌握这些类型及其转换规则是Python编程的基础。
207 33
|
2月前
|
数据采集 分布式计算 大数据
不会Python,还敢说搞大数据?一文带你入门大数据编程的“硬核”真相
不会Python,还敢说搞大数据?一文带你入门大数据编程的“硬核”真相
77 1
|
3月前
|
设计模式 安全 Python
Python编程精进:正则表达式
正则表达式是一种强大的文本处理工具,用于搜索、匹配和提取模式。本文介绍了正则表达式的语法基础,如`\d`、`\w`等符号,并通过实例展示其在匹配电子邮件、验证电话号码、处理日期格式等场景中的应用。同时,文章提醒用户注意性能、编码、安全性等问题,避免常见错误,如特殊字符转义不当、量词使用错误等。掌握正则表达式能显著提升文本处理效率,但需结合实际需求谨慎设计模式。
134 2
|
4月前
|
数据采集 安全 BI
用Python编程基础提升工作效率
一、文件处理整明白了,少加两小时班 (敲暖气管子)领导让整理100个Excel表?手都干抽筋儿了?Python就跟铲雪车似的,哗哗给你整利索!
113 11
|
6月前
|
人工智能 Java 数据安全/隐私保护
[oeasy]python081_ai编程最佳实践_ai辅助编程_提出要求_解决问题
本文介绍了如何利用AI辅助编程解决实际问题,以猫屎咖啡的购买为例,逐步实现将购买斤数换算成人民币金额的功能。文章强调了与AI协作时的三个要点:1) 去除无关信息,聚焦目标;2) 将复杂任务拆解为小步骤,逐步完成;3) 巩固已有成果后再推进。最终代码实现了输入验证、单位转换和价格计算,并保留两位小数。总结指出,在AI时代,人类负责明确目标、拆分任务和确认结果,AI则负责生成代码、解释含义和提供优化建议,编程不会被取代,而是会更广泛地融入各领域。
185 28
|
6月前
|
机器学习/深度学习 数据可视化 TensorFlow
Python 高级编程与实战:深入理解数据科学与机器学习
本文深入探讨了Python在数据科学与机器学习中的应用,介绍了pandas、numpy、matplotlib等数据科学工具,以及scikit-learn、tensorflow、keras等机器学习库。通过实战项目,如数据可视化和鸢尾花数据集分类,帮助读者掌握这些技术。最后提供了进一步学习资源,助力提升Python编程技能。

推荐镜像

更多