python复制地址不同有问题_Python里list的复制问题

写代码的时候发现的……太傻了……

查了一下发现里面还有学问,尤其是对列表里嵌套列表要格外注意!

浅拷贝

意思是修改了原列表/复制列表里的值,另一个列表也会被改变。可以理解为它们的内存是同一块地方?只是给了一个新的指针指向那里。所以无论改哪个,另一个都会被修改。

什么时候会出现浅拷贝?

我可以总结为没有使用deepcopy()的全是浅拷贝吗?

python里列表list采用“=”赋值的时候

当修改等号右边的原list时,新list也会改变。

>>> x = [1,2,3,4]

>>> y = x

>>> y.pop()

4

>>> y

[1, 2, 3]

>>> x

[1, 2, 3]

list采用“*”复制多个列表的时候,其实和上面相同,遇到嵌套列表的时候会出问题

>>> A = [[None,None]]

>>> B = A*3

>>> B[0][0]=0

>>> A

[[0, None]]

>>> B

[[0, None], [0, None], [0, None]]

=========== 通过id()查看内存地址

>>> id(B[0])

44594056L

>>> id(B[2])

44594056L

============= 看到A、B里面元素的内存是一样的!

>>> id(B[2][0])

31897360L

>>> id(B[2][1])

499518584L

>>> id(B[1][0])

31897360L

>>> id(B[1][1])

499518584L

>>> id(A[0][1])

499518584L

>>> id(A[0][0])

31897360L

>>> id(B[0])

44594056L

>>> id(A[0])

44594056L

==============疑问!!!!!! 这个A的地址是啥呀?为啥不是44560456L呢???

>>> id(A)

44595080L

>>> id(B)

44560456L

采用copy()函数

Python2.7里list没有这个内置函数,会报错,但是看到有人用,Python3应该有吧…

>>> z = x.copy()

Traceback (most recent call last):

File "", line 1, in

AttributeError: 'list' object has no attribute 'copy'

在没有嵌套的时候,或者字典嵌套列表的时候,copy()是可以复制字典不会被修改的。。那看来是list自己的问题。。

>>> a = {'x':11,'y':22}

>>> a.copy()

{'y': 22, 'x': 11}

>>> b = a.copy()

>>> b.popitem()

('y', 22)

>>> a

{'y': 22, 'x': 11}

>>> b

{'x': 11}

=========================

>>> a = {'x':[11, 22], 'y':[33,44]}

>>> b = a.copy()

>>> a['x']=13

>>> b

{'y': [33, 44], 'x': [11, 22]}

>>> a

{'y': [33, 44], 'x': 13}

>>> a['y']=[33,46]

>>> b

{'y': [33, 44], 'x': [11, 22]}

用for循环生成列表:

old = [1,[1,2,3],3]

new = []

for i in range(len(old)):

new.append(old[i])

print('Before:')

print(old)

print(new)

new[0] = 3

new[1][0] = 3

print('After:')

print(old)

print(new)

结果:

Before:

[1, [1, 2, 3], 3]

[1, [1, 2, 3], 3]

After:

[3, [3, 2, 3], 3]

[3, [3, 2, 3], 3]

使用切片:

old = [1,[1,2,3],3]

new = old[:]

print('Before:')

print(old)

print(new)

new[0] = 3

new[1][0] = 3

print('After:')

print(old)

print(new)

结果:

Before:

[1, [1, 2, 3], 3]

[1, [1, 2, 3], 3]

After:

[3, [3, 2, 3], 3]

[3, [3, 2, 3], 3]

解决方法

采用深复制的方法!

深复制

介绍

就是在内存里新开了一片地方存复制的数据,指针指的是不同的地址。

实现

使用deepcopy()函数,需要引入copy包:

>>> import copy

>>> z = copy.deepcopy(x)

>>> z.pop()

3

>>> z

[1, 2]

>>> x

[1, 2, 3]

import copy

old = [1,[1,2,3],3]

new = copy.deepcopy(old)

print('Before:')

print(old)

print(new)

new[0] = 3

new[1][0] = 3

print('After:')

print(old)

print(new)

结果:

Before:

[1, [1, 2, 3], 3]

[1, [1, 2, 3], 3]

After:

[1, [1, 2, 3], 3]

[3, [3, 2, 3], 3]

解决“*”的使用问题:使用新创建的列表为每个复制的对象赋值

>>> A = [None]

>>> B = [A*2 for i in range(3)]

>>> B

[[None, None], [None, None], [None, None]]

>>> A

[1]

>>> B[0][0]=2

>>> A

[1]

>>> B

[[2, None], [None, None], [None, None]]

注意*和for搭配使用!给我整的有点蒙了……对比下面3个栗子

>>> A[0]=1

>>> B

[[None, None], [None, None], [None, None]]

>>> A

[1]

>>> B[0][0]=1

>>> A

[1]

>>> B[0][0]=2

>>> A

[1]

>>> B # 明显看到只修改了B的一个值,A的值并没有改变。

[[2, None], [None, None], [None, None]]

====================== 这个就是 上面提到过的嵌套列表用for是浅复制呀!

>>> old = [1,[1,2,3],3]

>>> new = [old for i in range(1)]

>>> new

[[1, [1, 2, 3], 3]]

>>> old

[1, [1, 2, 3], 3]

>>> new[0][0] = 3

>>> new

[[3, [1, 2, 3], 3]]

>>> old

[3, [1, 2, 3], 3]

======================== for和“*”一起就变成深复制了?

>>> old = [1,[1,2,3],3]

>>> new = [old for i in range(2)]

>>> new

[[1, [1, 2, 3], 3], [1, [1, 2, 3], 3]]

>>> new[0][0]

1

>>> new[0][0]=3

>>> old

[3, [1, 2, 3], 3]

>>> new = [old*1 for i in range(2)]

>>> new

[[3, [1, 2, 3], 3], [3, [1, 2, 3], 3]]

>>> new[0][0]=1

>>> new

[[1, [1, 2, 3], 3], [3, [1, 2, 3], 3]]

>>> old

[3, [1, 2, 3], 3]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值