首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

你真的了解python参数的传递机制吗

Hello,小伙伴们,我是知道。

在工作中,很多人经常会遇到:代码写完一测试,发现结果和自己期望的不一样,于是开始一层层地 debug。花了很多时间,可到最后才发现,是传参过程中数据结构的改变,导致的程序问题。

比如,我将一个列表作为参数传入另一个函数,期望列表在函数运行结束后不变,但是往往事与愿违,由于某些操作,它的值改变了,那就很有可能带来后续程序一系列的错误。

因此,了解 Python 中参数的传递机制,这往往能让我们写代码时少犯错误,提高效率,是具有十分重要的意义。今天我们就一起来学习一下,Python 中参数是如何传递的。

什么是值传递和引用传递

有两种常见的参数传递:值传递和引用传递。

值传递,通常就是拷贝参数的值,然后传递给函数里的新变量。这样,原变量和新变量之间互相独立,互不影响。

引用传递,通常是指把参数的引用传给新的变量,这样,原变量和新变量就会指向同一块内存地址。如果改变了其中任何一个变量的值,那么另外一个变量也会相应地随之改变。

那么 Python 中,参数传递到底是如何进行的呢?它们到底属于值传递、引用传递,还是其他呢?

Python 变量及其赋值

先来看一段示例代码:

这里首先将 1 赋值于 a,即 a 指向了 1 这个对象,接着 b = a 则表示,让变量 b 也同时指向 1 这个对象。(注:Python 里的对象可以被多个变量所指向或引用)

最后执行 a = a + 1。需要注意的是,Python 的数据类型,例如整型(int)、字符串(string)等等,是不可变的。所以,a = a + 1,并不是让 a 的值增加 1,而是表示重新创建了一个新的值为 2 的对象,并让 a 指向它。但是 b 仍然不变,仍然指向 1 这个对象。因此,最后的结果是,a 的值变成了 2,而 b 的值不变仍然是 1。

通过这个例子你可以看到,这里的 a 和 b,开始只是两个指向同一个对象的变量而已,或者你也可以把它们想象成同一个对象的两个名字。简单的赋值 b = a,并不表示重新创建了新对象,只是让同一个对象被多个变量指向或引用。

同时,指向同一个对象,也并不意味着两个变量就被绑定到了一起。如果你给其中一个变量重新赋值,并不会影响其他变量的值。明白了这个基本的变量赋值例子,我们再来看一个列表的例子:

同样的,我们首先让列表 和同时指向了这个对象。

由于列表是可变的,所以 不会创建新的列表,只是在原列表的末尾插入了元素 4,变成。由于 和同时指向这个列表,所以列表的变化会同时反映在 和这两个变量上,那么, 和 的值就同时变为了。

另外,需要注意的是,Python 里的变量可以被删除,但是对象无法被删除。比如下面的代码:

删除了 这个变量,从此以后你无法访问 l,但是对象仍然存在。Python 程序运行时,其自带的垃圾回收系统会跟踪每个对象的引用。如果除了 外,还在其他地方被引用,那就不会被回收,反之则会被回收。

由此可见,在 Python 中:

变量的赋值,只是表示让变量指向了某个对象,并不表示拷贝对象给变量;而一个对象,可以被多个变量所指向。

可变对象(列表,字典,集合等等)的改变,会影响所有指向该对象的变量。

对于不可变对象(字符串、整型、元组等等),所有指向该对象的变量的值总是一样的,也不会改变。但是通过某些操作(+= 等等)更新不可变对象的值时,会返回一个新的对象。

变量可以被删除,但是对象无法被删除。

Python 函数的参数传递

Python 的参数传递是赋值传递 ,或者叫作对象的引用传递。Python 里所有的数据类型都是对象,所以参数传递时,只是让新变量与原变量指向相同的对象而已,并不存在值传递或是引用传递一说,代码示例:

这里的参数传递,使变量 x 和 y 同时指向了 1 这个对象。但当我们执行到 x = 2 时,系统会重新创建一个值为 2 的新对象,并让 x 指向它;而 y 仍然指向 1 这个对象。所以,y的值不变,仍然为 1。

那么对于上述例子的情况,是不是就没有办法改变 y 的值了呢?答案当然是否定的,我们只需稍作改变,让函数返回新变量,赋给 y。这样,y 就指向了一个新的值为 2 的对象,y的值也因此变为 2。

不过,当可变对象当作参数传入函数里的时候,改变可变对象的值,就会影响所有指向它的变量。比如下面的例子:

这里 x 和 y 先是同时指向值为的列表。不过,由于列表可变,执行 append() 函数,对其末尾加入新元素 4 时,变量 x 和 y 的值也都随之改变了。

但是,下面这个例子,看似都是给列表增加了一个新元素,却得到了明显不同的结果。

为什么y 仍然是,而不是呢?

要注意,这里,表示创建了一个“末尾加入元素 4“的新列表,并让 x 指向这个新的对象。这个过程与y 无关,因此y的值不变。当然,同样的,如果要改变 y 的值,我们就得让上述函数返回一个新列表,再赋予y 即可,这里你尤其要记住的是,改变变量和重新赋值的区别:

小结

今天,我们一起探讨了 Python 的变量及其赋值的基本原理,并且解释了 Python 中参数是如何传递的。和其他语言不同的是,Python 中参数的传递既不是值传递,也不是引用传递,而是赋值传递,或者是叫对象的引用传递。

需要注意的是,这里的赋值或对象的引用传递,不是指向一个具体的内存地址,而是指向一个具体的对象。

可变对象,当其改变时,所有指向这个对象的变量都会改变。

不可变对象,简单的赋值只能改变其中一个变量的值,其余变量则不受影响。

清楚了这一点,如果你想通过一个函数来改变某个变量的值,通常有两种方法。一种是直接将可变数据类型(比如列表,字典,集合)当作参数传入,直接在其上修改;第二种则是创建一个新变量,来保存修改后的值,然后将其返回给原变量。在实际工作中,我们更倾向于使用后者,因为其表达清晰明了,不易出错。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230211A06IEU00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券