【发布时间】:2018-04-14 14:30:36
【问题描述】:
在了解了列表和方框和指针图之后,我决定为自己创建随机的东西并测试我的知识。我将使用浅拷贝和疑似浅拷贝这两个词,因为我不确定它们的定义是否正确。我的问题是提供此类代码行为的原因,请告诉我我是否在思考。
代码 A
from copy import *
x=[1,[2,[3,[4]]]] #normal copy/hardcopy
a=x
v=list(x) #suspected shallow copy
y=x.copy() #shallow copy
z=deepcopy(x) #theoretical deep copy
w=x[:] #suspected shallow copy
def test():
print("Original:",x)
print("hardcopy:",a)
print("suspected shallow copy",v)
print("shallow copy",y)
print("deep copy:",z)
print("suspected shallow copy",w)
x[1]=x[1]+[4]
test()
输出 A:
Original: [1, [2, [3, [4]], 4]]
hardcopy: [1, [2, [3, [4]], 4]]
suspected shallow copy [1, [2, [3, [4]]]]
shallow copy [1, [2, [3, [4]]]]
deep copy: [1, [2, [3, [4]]]]
suspected shallow copy [1, [2, [3, [4]]]]
代码 B
a=(1,2,[1,2,3])
def shallow_copy(x):
tup=()
for i in x:
tup+=(i,)
return tup
def hardcopy(x):
return x
b=hardcopy(a)
c=shallow_copy(a)
a[2]+=[3]
输出 B: 我在这里看到 IDLE 中的 TypeError,但列表元素的突变仍然完成,并且跨越 ALL a,b,c
从输出 B 继续:
a[2][0]=a[2][0]+99
a,b,c
输出 C:
((1, 2, [100, 2, 3, 3]), (1, 2, [100, 2, 3, 3]), (1, 2, [100, 2, 3, 3]))
代码 D:
a=[1,2,(1,2,3)]
def shallow_copy(x):
tup=[]
for i in x:
tup+=[i]
return tup
def hardcopy(x):
return x
b=hardcopy(a)
c=shallow_copy(a)
d=a.copy()
a[2]=a[2]+(4,)
a,b,c,d
输出 D:
[1, 2, (1, 2, 3, 4)], [1, 2, (1, 2, 3, 4)],
[1, 2, (1, 2, 3)], [1, 2, (1, 2, 3)]
从输出 A,我们观察到以下内容: 1)对于具有浅拷贝的列表,执行
x[1]=x[1]+[4]不会影响浅拷贝。我上面的原因可能是a)
=后跟+执行__add__而不是__iadd__(即+=),并且执行__add__不应修改对象,仅更改一个指针的值(x以及在这种情况下的硬拷贝)
这在输出 B 中得到了进一步的支持,但在输出 C 中有些矛盾,部分原因可能是下面的原因 (b),但不能太确定。
b) 我们在第一层执行了这个(只有一个切片操作符),也许有某种规则阻止这些元素被修改。
输出 B 和输出 C 都支持这一点,尽管输出 B 可能被认为在第一层,但可以将其视为增加第二层中的元素,它符合上述观察。
2) 输出B出现TypeError,但仍然执行的原因是什么?我知道是否触发异常取决于您实际更改的最终顺序(本例中的列表),但为什么仍然存在
TypeError: 'tuple' object does not support item assignment?
我已就上述问题提出了我的看法。我很欣赏关于这个问题的任何想法(最好是理论解决方案),因为我对编程还是比较陌生。
【问题讨论】:
-
使用
id(your obj)获得一个唯一的ID - 打印并比较它们 - 很容易确定事情是否相同。a = x只是 b 拥有的数据的另一个“名称”,它根本没有副本。 -
@PatrickArtner 我知道在实践考试中检查的方法。但是,这类题目喜欢出现在我的笔试中,所以我必须从理论的角度推导出一种理解它们的方法。
标签: python python-3.x list