Python关于实参随形参改变而改变的问题

 更新时间:2024年11月20日 08:47:33   作者:长命百岁️  
本文通过实验总结了Python中可变和不可变数据类型的区别,并提出了通过使用.copy()方法或deepcopy()函数来保持可变数据不变的解决方案

前言

今天在实验过程中,发现将字典作为函数的形参传入函数,在函数内改变形参,会导致传入的字典的值也发生相应的改变。

这与c++不同,令我疑惑,遂写此文。

简单实验

我们对常见的数据类型进行实验,检测形参的该表是否会改变传入的实参。

变量

def change(a):
    a = 2
    print(a)
b = 1
change(b)
print(b)
>>2
>>1

可见,变量的值并没有随形参的改变而改变

元组

def change(a):
    a = a[:2]
    print(a)
b = (1, 2, 3)
change(b)
print(b)
>>(1, 2)
>>(1, 2, 3)

可见,元组没有随形参的改变而改变

列表

def change(a):
    a.append(1)
    print(a)
b = [2, 3]
change(b)
print(b)
>>[2, 3, 1]
>>[2, 3, 1]

可见,列表随着形参的改变而发生改变

字典

def change(a):
    a[1] = 100
    print(a)
b = {1: 1, 2: 2}
change(b)
print(b)
>>{1: 100, 2: 2}
>>{1: 100, 2: 2}

可见,字典随着形参的改变而发生改变

原因

我们遇到了可变不可变数据类型之间的差异。在Python中,数据类型可以是可变的,也可以是不可变的。

我们通常使用的(整数,浮点数,字符串,布尔值和元组)数据类型都是不可变的,但是列表和字典是可变的。

这意味着全局列表或字典即使在函数内部使用时也可以更改,我们通过上面的例子也能看出这个问题。

不可变数据举例

a = 1

变量a 的作用类似于一个指向 1 的指针。

变量的数据类型是不可变的,变量一旦创建就不能别改变。

如果我们执行 a = a + 1

我们实际上不是将 1 更新到 2,而是指针从 1 指向了 2。

可变数据距离

list1 = [1, 2, 3]

如果我们在列表的末尾添加一个值,我们不是将list1指向另一个列表,而是直接更新现有列表。

如果我们创建多个列表变量,只要他们指向同一个列表,那么当列表发生改变时,这些列表变量都会发生变化。

list1 = [1, 2, 3]
list2 = list1
list1.append(4)
print(list1)
print(list2)
>>[1, 2, 3, 4]
>>[1, 2, 3, 4]

心得

从这两个例子中,我们可以直观感受到可变数据类型与不可变数据类型之间的区别。

我们对可变数据的操作,是直接在其本身上进行操作的。

对不可变数据的操作,是将指针指向另一个位置,而不是更改其本身。

保持可变数据不变

我们在写代码时,经常会编写各种函数。我们不希望传入函数的实参,会在函数内部被改变。那应该怎么办呢?

其实很简单,使用.copy()方法复制列表或字典即可。

list1 = [1, 2, 3]
list2 = list1.copy()
list1.append(4)
print(list1)
print(list2)
>>[1, 2, 3, 4]
>>[1, 2, 3]

.copy()方法会创建一个新的副本,这样list2就不会指向list1指向的列表,而是指向一个新的列表。

这样的话,list1list2就相互独立,互不影响了。

def change(a):
    temp = a.copy()
    temp.append(4)
    print(temp)
list1 = [1, 2, 3]
change(list1)
print(list1)
>>[1, 2, 3, 4]
>>[1, 2, 3]

可见,这样我们就解决了形参的改变带来的实参改变的问题。对于字典也是一样的。

补充

深拷贝与浅拷贝

>>> import copy
>>> origin = [1, 2, [3, 4]]
#origin 里边有三个元素:1, 2,[3, 4]
>>> cop1 = copy.copy(origin)
>>> cop2 = copy.deepcopy(origin)
>>> cop1 == cop2  # 判断 cop1 和 cop2 的值是否相同
True
>>> cop1 is cop2  # 判断 cop1 和 cop2 是否是同一个对象
False 
#cop1 和 cop2 看上去相同,但已不再是同一个object
>>> origin[2][0] = "hey!" 
>>> origin
[1, 2, ['hey!', 4]]
>>> cop1
[1, 2, ['hey!', 4]]
>>> cop2
[1, 2, [3, 4]]

copy对于一个复杂对象的子对象并不会完全复制。什么是复杂对象的子对象呢?

比如列表里的嵌套列表(多维列表),字典里的嵌套字典(多维字典)都是复杂对象的子对象。

对于子对象,python会将其当做一个公共镜像存储起来,所有对它的复制都会被当成引用(就是拿指针指向同一块区域)。所以,其中一个引用的值发生改变时,其他引用的值也会发生改变。

复制复杂对象,我们也想全盘复制(包括子对象),这时我们就可以使用deepcopy()函数进行深拷贝

import copy
a = [1, 2, [3, 4]]
b = copy.deepcopy(a)  # 深拷贝

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Python在信息学竞赛中的运用及Python的基本用法(详解)

    Python在信息学竞赛中的运用及Python的基本用法(详解)

    下面小编就为大家带来一篇Python在信息学竞赛中的运用及Python的基本用法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • python应用之如何使用Python发送通知到微信

    python应用之如何使用Python发送通知到微信

    现在通过发微信信息来做消息通知和告警已经很普遍了,下面这篇文章主要给大家介绍了关于python应用之如何使用Python发送通知到微信的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • pytorch中节约显卡内存的方法和技巧

    pytorch中节约显卡内存的方法和技巧

    显存不足是很多人感到头疼的问题,毕竟能拥有大量显存的实验室还是少数,而现在的模型已经越跑越大,模型参数量和数据集也越来越大,所以这篇文章给大家总结了一些pytorch中节约显卡内存的方法和技巧,需要的朋友可以参考下
    2023-11-11
  • Python绘制圆形方法及turtle模块详解

    Python绘制圆形方法及turtle模块详解

    这篇文章主要给大家介绍了关于Python绘制圆形方法及turtle模块详解的相关资料,Turtle库是Python语言中一个很流行的绘制图像的函数库,文中介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • Python的设计模式编程入门指南

    Python的设计模式编程入门指南

    这篇文章主要介绍了Python的设计模式编程入门指南,设计模式主要指面对某些问题时需要用到的编程思想,需要的朋友可以参考下
    2015-04-04
  • 将python文件打包exe独立运行程序方法详解

    将python文件打包exe独立运行程序方法详解

    这篇文章主要介绍了将python文件打包exe独立运行程序方法详解,需要的朋友可以参考下
    2020-02-02
  • Python实现使用request模块下载图片demo示例

    Python实现使用request模块下载图片demo示例

    这篇文章主要介绍了Python实现使用request模块下载图片,结合完整实例形式分析了Python基于requests模块的流传输文件下载操作相关实现技巧,需要的朋友可以参考下
    2019-05-05
  • Python datetime包函数简单介绍

    Python datetime包函数简单介绍

    这篇文章主要介绍了Python datetime包函数简单介绍,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • pycharm恢复默认设置或者是替换pycharm的解释器实例

    pycharm恢复默认设置或者是替换pycharm的解释器实例

    今天小编就为大家分享一篇pycharm恢复默认设置或者是替换pycharm的解释器实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-10-10
  • python使用opencv换照片底色的实现

    python使用opencv换照片底色的实现

    这篇文章主要介绍了python使用opencv换照片底色的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11

最新评论