第115天:Python 到底是值传递还是引用传递

简介: 第115天:Python 到底是值传递还是引用传递

我们平时写的 Python 程序中充斥着大量的函数,包括系统自带函数和自定义函数,当我们调用函数时直接将参数传递进去然后坐等接收返回值即可,简直不要太好用。那么你知道函数的参数是怎么传递的么,是值传递还是引用传递呢,什么又是值传递和引用传递呢?


这个问题对于很多初学者还是比较有难度的,看到这里你可以稍加停顿,自己思考一下,看看自己是否真正理解了。很多人只是知道概念但是让他说他又说不清楚,思考过后如果你还觉得模糊的话,往下仔细看,我今天就带着你深入剖析下函数的参数传递机制。


为了搞清楚函数的参数传递机制,你必须先彻底理解形参和实参。例如下面的 sayHello 函数,括号里面的 name 就是形参,而当调用函数时传递的 name 是实参。


def sayHello(name): # name 是形式参数    print("Hello %s" % name)
name = "hanmeimei" # name 是实际参数sayHello(name)
# 输出结果Hello hanmeimei


值传递 OR 引用传递


上面我们说了,当调用函数时我们会把实际参数传递给形式参数。而这个传递过程有两种,就是我们上文说的值传递和引用传递了。


顾名思义,所谓值传递就是指在传递过程中将实际参数的值复制一份传递给形式参数,这样即使在函数执行过程中对形式参数进行了修改,形式参数也不会有所改变,因为二者互不干扰。而引用传递是值将实际参数的引用传递给实际参数,这样二者就会指向同一块内存地址,在函数执行过程中对形式参数进行了修改,形式参数也会一并=被修改。

为了故事的顺利发展,我们先来看看 Python 中关于变量的赋值。



>>> a = 10>>> b = a>>> a = a + 10>>> a20>>> b10>>>


在上述的例子中,我们声明了一个变量 a,其值为 10,然后将 b 也指向 a,这是在内存中的布局是这样的,变量 a 和 b 会指向同一个对象 10,而不是给 b 重新生成一个新的对象。


image.png


由此可知,同一个对象是可以被多个对象引用的。


当执行完 a = a + 10 后,因为整数是不可变对象,所以并不会将 10 变成 20,而是生成一个新的对象 20 ,然后 a 会指向这个新的对象。b 还是指向旧对象 10。


image.png


所以,最后就是 a 为 20,而 b 为 10。


理解了上面的赋值过程之后,我们再来看看参数的传递。老规矩,还是直接看例子吧,代码是不会骗人的。


def swap(a, b):    a, b = b, a    print("in swap a = %d and b = %d " % (a, b))
a = 100b = 200swap(a, b)print("in main a = %d and b = %d " % (a, b))
## 输出结果in swap a = 200 and b = 100 in main a = 100 and b = 200


我们在函数 swap 中交换 a 和 b 的值,然后分别在主函数和 swap 函数中输出其结果,


由结果可知,swap 函数并不会改变实际参数 a,b 的值,因此我们可以得出结论,Python 函数参数是按照值传递的。


别急,不妨再看多一个例子。


def swap(list):    list.append(4)    print("in swap list is %s " % list)
list_x = [1, 2, 3]swap(list_x)print("in main list is %s " % list_x)
## 输出结果in swap list is [1, 2, 3, 4] in main list is [1, 2, 3, 4]


咦,值被改了,这不就是引用传递了么。于是,我们又得出结论,Python 函数参数是按照引用传递的。


这未免有点太不严谨了,事实上我们上面的第二个例子有点不太严谨,我稍微修改了下 swap 函数,咱们在看看测试结果。



def swap(list):    list = list + [4]    print("in swap list is %s " % list)
## 输出结果in swap list is [1, 2, 3, 4] in main list is [1, 2, 3]


我们只是更改了 swap 函数内一行代码,结果就完全不一样了。为了更好的理解其执行过程,我画了张图。


image.png


在第一个关于 list 的例子中,我们首先声明了一个列表,其中的元素为 [1,2,3],此时其内存布局如上图中的步骤一所示。list_x 指向内存地址为 OX7686934F 的区域。


当调用 swap 函数将 list_x 传递给形式参数 list 时,会将该地址直接传递过去,list 也会指向这个地址,如步骤二所示。


最后,由于列表是可变的,所以当 list 在向列表中添加元素时,list_x 自然会受到影响,因为二者指向的是同一块内存。


所以,这里也是值传递,只不过传递的值是对象的内存地址罢了。


第二个关于 list 的例子中,我们对 swap 函数进行了修改,其执行流程如下图所示。


image.png


在执行 swap 函数之前都与上面的例子毫无差别。在 swap 函数内部 list = list + [4] 表示新建一个末尾加入元素 4 的新的列表,并让 list 指向这个新的内存地址  OX7686936A。因为是生成了一个新的对象,与原对象无关,所以 list_x 不受影响。


简而言之,弄清楚改变变量和重新赋值的区别就好了,第一个例子中我们改变了变量的值,所以当函数执行结束后所有指向该对象的变量都会受影响。而重新赋值相当于重新生成一个新的对象并在新的对象上做操作,因此旧对象不受影响。


如果我们要想在函数中改变对象,第一可以传入可变数据类型(列表,字典,集合),直接改变;第二还可以创建一个新的对象,修改后返回。建议用后者,表达清晰明了,不易出错。


总结


本文介绍了 Python 函数的参数传递机制。理解了参数的传递过程和底层实现细节,写代码时将会少犯一些不必要的低级错误。


最后,无论是值传递还是引用传递,我们只需关注函数内部是否会生成新的对对象即可。凡是对原对象操作的函数,都会影响传递的实际参数;凡是生成了新对象的操作,都不会影响传递的实际参数。


目录
相关文章
|
Python
python之函数的参数传递(引用传递和值传递),查看变量的内存地址的方法
python之函数的参数传递(引用传递和值传递),查看变量的内存地址的方法
|
存储 C++ Python
Python到底是引用传递还是值传递?网上大多数教程都讲错了
或许在很多人的直观印象中,变量是一个容器;给变量赋值,就像是往一个存储的容器中填入一个数据;再次赋值就是把容器中的数据换掉。
|
存储 C++ 开发者
python|基础|值传递和引用传递
python|基础|值传递和引用传递
150 0
|
16天前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
15天前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
3天前
|
Unix Linux 程序员
[oeasy]python053_学编程为什么从hello_world_开始
视频介绍了“Hello World”程序的由来及其在编程中的重要性。从贝尔实验室诞生的Unix系统和C语言说起,讲述了“Hello World”作为经典示例的起源和流传过程。文章还探讨了C语言对其他编程语言的影响,以及它在系统编程中的地位。最后总结了“Hello World”、print、小括号和双引号等编程概念的来源。
97 80
|
21天前
|
存储 索引 Python
Python编程数据结构的深入理解
深入理解 Python 中的数据结构是提高编程能力的重要途径。通过合理选择和使用数据结构,可以提高程序的效率和质量
133 59
|
1天前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
14 2
|
15天前
|
小程序 开发者 Python
探索Python编程:从基础到实战
本文将引导你走进Python编程的世界,从基础语法开始,逐步深入到实战项目。我们将一起探讨如何在编程中发挥创意,解决问题,并分享一些实用的技巧和心得。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你提供有价值的参考。让我们一起开启Python编程的探索之旅吧!
41 10
|
18天前
|
机器学习/深度学习 人工智能 Java
Python 语言:强大、灵活与高效的编程之选
本文全面介绍了 Python 编程语言,涵盖其历史、特点、应用领域及核心概念。从 1989 年由 Guido van Rossum 创立至今,Python 凭借简洁的语法和强大的功能,成为数据科学、AI、Web 开发等领域的首选语言。文章还详细探讨了 Python 的语法基础、数据结构、面向对象编程等内容,旨在帮助读者深入了解并有效利用 Python 进行编程。
下一篇
DataWorks