列表的复制

原文地址
https://blog.csdn.net/zhaogeno1/article/details/80530928

不对的复制

old_list = ['hello', 'world']
new_list = old_list
old_list.append('nihao')
print(new_list)
print(id(new_list))
print(id(old_list))
#输出 ['hello', 'world', 'nihao']
30160296
30160296
#可以发现地址时一样的

此时旧列表发生变化的时候新列表也会发生变化,这是不正确的复制,原来,在Pyhton中使用赋值(=)的时候,实际上只是给新变量指向一个引用,简单一点讲就是当我们执行a=b时,实际上进行的操作是将a的内存地址赋值给了b,此时a和b指向的是同一个内存地址,并不是开辟一个新的内存地址给b,所以每当内存地址里的值发生变化的时候,b的值也会随之变化

那么应该如何正确的复制
如果列表内为不可变数据时可用以下方法

# 方法一:
new_list1 = old_list[:]
# 方法二:
# list()将一个元组作为参数,并把它转化为列表,如果参数是列表,将会原样返回:
new_list2 = list(old_list)
# 方法三:
new_list3 = []
for item in old_list: new_list3.append(item)
# 方法四:列表推导式
new_list4 = [i for i in old_list]
# 方法五 通过extend可以将另一个集合中的元素逐一添加到列表中
new_list5 = []
new_list5.extend(old_list)
# 方法六:
import copy
new_list6 = copy.copy(old_list)

此时是列表内应该为不可变数据类型时可使用,但是不能用于可变数据类型
比如

extra_list=['nihao']
old_list = ['hello','world',extra_list]
print (old_list)
new_list=[i for i in old_list]
print(new_list)
extra_list.append('666666')
print(new_list)
print(old_list)
print (id(new_list))
print (id(old_list))

输出为

['hello', 'world', ['nihao']]
['hello', 'world', ['nihao']]
['hello', 'world', ['nihao', '666666']]
['hello', 'world', ['nihao', '666666']]
18991864
18561584 
#他们的地址不同,但是都使用了相同的extra_list
#此时你会发现,似乎这又跟我们使用赋值(=)的结果有些类似,但又有所不同。其实在我们使用上面几种复制列表的时候,它实现的是一种浅拷贝。浅拷贝呢,其实比赋值高级一点,就是他会把列表中的值都复制给新对象,但是如果列表中的值是可变数据(列表、字典、函数、类等),他只会复制一个引用。

深拷贝
那么,我们如果拷贝的列表中带有可变数据时该怎么进行复制呢?很简单,有浅拷贝就会有深拷贝,深拷贝呢,就是将所有东西都复制一遍给新对象,解除你的所有后顾之忧。

import  copy
extra_list=['nihao']
old_list = ['hello','world',extra_list]
print (old_list)
new_list=copy.deepcopy(old_list)
print(new_list)
extra_list.append('666666')
print(new_list)
print(old_list)

输出

['hello', 'world', ['nihao']]
['hello', 'world', ['nihao']]
['hello', 'world', ['nihao']]
['hello', 'world', ['nihao', '666666']]

速度差异
我们可以来看下以下数据,是使用各种不同方法拷贝一个同个列表所花费的时间

110.59 sec (105.9us/itn) -  copy.deepcopy(old_list)
20.325 sec (3.25us/itn) - for item in old_list: new_list.append(item)
30.217 sec (2.17us/itn) - [i for i in old_list] (a list comprehension)
40.186 sec (1.86us/itn) - copy.copy(old_list)
50.075 sec (0.75us/itn) - list(old_list)
60.053 sec (0.53us/itn) - new_list = []; new_list.extend(old_list)
70.039 sec (0.39us/itn) - old_list[:] (list slicing)

由上面可以看出,使用深拷贝所花费的时间是其他方法的至少30倍以上,这也是我们为什么要举出上面那些方法的原因。
我们平常在复制列表的时候,大多数列表的内容都是不变数据,如果数据量大的话,使用深拷贝就完全没有必要,会大大降低程序运行效率。
所以,我们在使用时可以根据我们的实际情况来选择不同的复制方法,以便提高我们的工作效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值