Python列表片语法没有明显的原因使用

我偶尔会看到Python代码中使用的列表片语法,如下所示:

newList = oldList[:] 

这当然是一样的:

 newList = oldList 

还是我错过了什么?

就像NXC说的那样,Pythonvariables名实际上指向一个对象,而不是内存中的特定位置。

newList = oldList将创build两个不同的variables指向同一个对象,因此,更改oldList也会更改newList

但是,当您执行newList = oldList[:] ,它会“切片”列表,并创build一个新的列表。 [:]的默认值是0和列表的结尾,所以它复制一切。 因此,它会创build一个包含在第一个数据中的所有数据的新列表,但两者都可以在不改变其他数据的情况下进行更改。

[:] 浅拷贝列表,制作包含对原始列表成员的引用的列表结构的副本。 这意味着副本上的操作不会影响原始结构。 但是,如果您对列表成员做了某些操作,那么这两个列表仍然会引用它们,所以如果通过原始成员访问成员,则会显示更新。

深层复制也将复制所有列表成员。

下面的代码片段显示了一个浅层副本的行动。

 # ================================================================ # === ShallowCopy.py ============================================= # ================================================================ # class Foo: def __init__(self, data): self._data = data aa = Foo ('aaa') bb = Foo ('bbb') # The initial list has two elements containing 'aaa' and 'bbb' OldList = [aa,bb] print OldList[0]._data # The shallow copy makes a new list pointing to the old elements NewList = OldList[:] print NewList[0]._data # Updating one of the elements through the new list sees the # change reflected when you access that element through the # old list. NewList[0]._data = 'xxx' print OldList[0]._data # Updating the new list to point to something new is not reflected # in the old list. NewList[0] = Foo ('ccc') print NewList[0]._data print OldList[0]._data 

在python shell中运行它会得到下面的logging。 我们可以看到这个列表是用旧对象的副本制作的。 其中一个对象的状态可以通过旧列表进行引用更新,当通过旧列表访问对象时可以看到更新。 最后,改变新列表中的引用可以被看作不反映在旧列表中,因为新列performance在指的是不同的对象。

 >>> # ================================================================ ... # === ShallowCopy.py ============================================= ... # ================================================================ ... # ... class Foo: ... def __init__(self, data): ... self._data = data ... >>> aa = Foo ('aaa') >>> bb = Foo ('bbb') >>> >>> # The initial list has two elements containing 'aaa' and 'bbb' ... OldList = [aa,bb] >>> print OldList[0]._data aaa >>> >>> # The shallow copy makes a new list pointing to the old elements ... NewList = OldList[:] >>> print NewList[0]._data aaa >>> >>> # Updating one of the elements through the new list sees the ... # change reflected when you access that element through the ... # old list. ... NewList[0]._data = 'xxx' >>> print OldList[0]._data xxx >>> >>> # Updating the new list to point to something new is not reflected ... # in the old list. ... NewList[0] = Foo ('ccc') >>> print NewList[0]._data ccc >>> print OldList[0]._data xxx 

正如已经回答的那样,我只是简单地添加一个示例:

 >>> a = [1, 2, 3, 4] >>> b = a >>> c = a[:] >>> b[2] = 10 >>> c[3] = 20 >>> a [1, 2, 10, 4] >>> b [1, 2, 10, 4] >>> c [1, 2, 3, 20] 

从来不认为Python中的“a = b”意味着“将b复制到a”。 如果双方都有变数,你就不能真正知道这一点。 相反,可以把它看作是“给一个额外的名字”。

如果b是不可变对象(如数字,元组或string),那么是的,效果是你得到一个副本。 但是那是因为当你处理不可变的事情时(根据定义,它们可能被称为只读 ,不可或者WORM ),你总会得到一个副本。

如果b是可变的,那么你总是需要做一些额外的事情来确保你有一个真正的副本总是 使用列表,就像一个切片一样简单:a = b [:]。

可变性也是这样的原因:

 def myfunction(mylist=[]): pass 

…并不完全符合你的想法。

如果你来自C背景:“=”的剩余部分总是一个指针。 所有variables总是指针。 如果将variables放在列表中:a = [b,c],则将指针指向a和b指向的列表中的b和c指向的值。 如果你设置一个[0] = d,位置0的指针现在指向任何指向的点。

另请参阅复制模块: http : //docs.python.org/library/copy.html

浅拷贝:(从一个位置复制大块内存到另一个位置)

 a = ['one','two','three'] b = a[:] b[1] = 2 print id(a), a #Output: 1077248300 ['one', 'two', 'three'] print id(b), b #Output: 1077248908 ['one', 2, 'three'] 

深度复制:(复制对象参考)

 a = ['one','two','three'] b = a b[1] = 2 print id(a), a #Output: 1077248300 ['one', 2, 'three'] print id(b), b #Output: 1077248300 ['one', 2, 'three']