python中关于list.copy()的陷阱

今天遥感课正好学到卷积运算,然后又布置了作业。可是手工一个个算(敲计算器)太累了,于是我就在下一节计算机课上争取偷懒→_→比较顺利的是,懒是偷成了。但是写的程序有个小bug——就是会改变原始的输!入!数!据!

作为一个强迫症,输入数据肯定要有备份的嘛!于是便开始查找原因:一开始认为是类的问题,后来发现问题并不这么简单——

如图,self.table是原始输入数据,res是暂存的结果。先是把self.table复制一份给res.table,然后对res.table进行处理。嗯,一切都很正常!然后一运行……卧槽?self.table怎么也全变成4了?这不对啊!我不是copy了嘛!对了,一定是我copy用得不对,于是我在idle下进行了如下测试:

>>> lst=[1,2]

>>> a=lst.copy()

>>> a[0]=999

>>> a

[999, 2]

>>> lst

[1, 2]

很正常啊!这不是对的嘛?后来通过和同学的讨论,发现了这么一个神奇的现象:

>> >lst=[1,2]

>>> a=lst.copy()

>>> a[0]=999

>>> a

[999, 2]

>>> lst

[1, 2]

>>> lst=[1,2]

>>> a=lst.copy()

>>> lst is a

False

>>> lst[0] is a[0]

True

>>> a[0]=999

>>> lst[0] is a[0]

False

哇!原来copy后的列表确实和原列表不是一个东西,但是列表中对应的元素还是一个东西。但是由于整数不可被更改,所以当a[0]=999时,python会新开辟一个内存存999这个值,所以内存地址又不一样了。

回到最开始的程序中,由于被copy的列表时一个嵌套列表,即列表里的元素还是列表。而列表是可修改的,所以导致尽管看上去列表被copy了一个副本,里面的元素还是保持着关联性。所以,改了res.table[x][y]就相当于改了self.table[x][y]。

那么这个问题怎么解决呢?很简单,其实通过copy模块的copy.deepcopy方法就行了。如下图所示:

 

最后的最后,其实我很久以前(也没多久)在哪里看到过copy和deepcopy函数这个东西,也曾经理解过这些内容,但是因为记性不好= =今天又忘掉了,所以在自己的博客中水一篇这样的文章,提醒自己,也能为后来疑惑者解惑吧~

目前评论:1   其中:访客  0   博主  0


    Warning: A non-numeric value encountered in /www/wwwroot/i.pegasi.top/wp-content/themes/begin/inc/function/comment-template.php on line 31
  1. avatar Pegasus

    Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in /www/wwwroot/i.pegasi.top/wp-content/themes/begin/inc/function/setting.php on line 1367
评论加载中...

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

图片 表情