无明显原因使用的 Python 列表切片语法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/323689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python list slice syntax used for no obvious reason
提问by Charles Anderson
I occasionally see the list slice syntax used in Python code like this:
我偶尔会看到 Python 代码中使用的列表切片语法是这样的:
newList = oldList[:]
Surely this is just the same as:
当然,这与以下内容相同:
newList = oldList
Or am I missing something?
或者我错过了什么?
回答by ConcernedOfTunbridgeWells
[:]
Shallow copiesthe list, making a copy of the list structure containing references to the original list members. This means that operations on the copy do not affect the structure of the original. However, if you do something to the list members, both lists still refer to them, so the updates will show up if the members are accessed through the original.
[:]
浅拷贝列表,制作包含对原始列表成员的引用的列表结构的副本。这意味着对副本的操作不会影响原件的结构。但是,如果您对列表成员执行某些操作,两个列表仍会引用它们,因此如果通过原始访问成员,则会显示更新。
A Deep Copywould make copies of all the list members as well.
一个深复制会使所有的成员的拷贝。
The code snippet below shows a shallow copy in action.
下面的代码片段显示了一个正在运行的浅拷贝。
# ================================================================
# === 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
Running it in a python shell gives the following transcript. We can see the list being made with copies of the old objects. One of the objects can have its state updated by reference through the old list, and the updates can be seen when the object is accessed through the old list. Finally, changing a reference in the new list can be seen to not reflect in the old list, as the new list is now referring to a different object.
在 python shell 中运行它会给出以下成绩单。我们可以看到使用旧对象的副本制作的列表。其中一个对象可以通过旧列表通过引用更新其状态,当通过旧列表访问对象时可以看到更新。最后,可以看到更改新列表中的引用不会反映在旧列表中,因为新列表现在引用了不同的对象。
>>> # ================================================================
... # === 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
回答by Deinumite
Like NXC said, Python variable names actually point to an object, and not a specific spot in memory.
正如 NXC 所说,Python 变量名实际上指向一个对象,而不是内存中的特定位置。
newList = oldList
would create two different variables that point to the same object, therefore, changing oldList
would also change newList
.
newList = oldList
将创建指向同一对象的两个不同变量,因此,更改oldList
也会更改newList
。
However, when you do newList = oldList[:]
, it "slices" the list, and creates a new list. The default values for [:]
are 0 and the end of the list, so it copies everything. Therefore, it creates a new list with all the data contained in the first one, but both can be altered without changing the other.
但是,当您这样做时newList = oldList[:]
,它会“切片”列表,并创建一个新列表。的默认值为[:]
0 和列表末尾,因此它复制所有内容。因此,它会创建一个新列表,其中包含第一个列表中包含的所有数据,但两者都可以在不更改另一个的情况下进行更改。
回答by Charles Anderson
As it has already been answered, I'll simply add a simple demonstration:
由于已经回答了,我将简单地添加一个简单的演示:
>>> 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]
回答by kaleissin
Never think that 'a = b' in Python means 'copy b to a'. If there are variables on both sides, you can't really know that. Instead, think of it as 'give b the additional name a'.
永远不要认为 Python 中的“a = b”意味着“将 b 复制到 a”。如果双方都有变数,你就无法真正知道。相反,将其视为“给 b 附加名称 a”。
If b is an immutable object (like a number, tuple or a string), then yes, the effect is that you get a copy. But that's because when you deal with immutables (which maybe should have been called read only, unchangeableor WORM) you alwaysget a copy, by definition.
如果 b 是一个不可变对象(如数字、元组或字符串),那么是的,效果是您获得了一个副本。但那是因为当您处理不可变对象(它可能应该被称为read only、unchangeable或WORM)时,根据定义,您总是会得到一个副本。
If b is a mutable, you always have to do something extra to be sure you have a true copy. Always. With lists, it's as simple as a slice:?a = b[:].
如果 b 是可变的,你总是需要做一些额外的事情来确保你有一个真正的副本。总是。对于列表,它就像切片一样简单:?a = b[:]。
Mutability is also the reason that this:
可变性也是这个原因:
def myfunction(mylist=[]):
pass
... doesn't quite do what you think it does.
......并没有完全按照你的想法去做。
If you're from a C-background: what's left of the '=' is a pointer, always. All variables are pointers, always. If you put variables in a list:?a = [b, c], you've put pointers to the values pointed to by b and c in a list pointed to by a. If you then set a[0] = d, the pointer in position 0 is now pointing to whatever d points to.
如果您来自 C 背景:“=”的左边总是一个指针。所有变量都是指针,始终。如果将变量放在列表中:?a = [b, c],则将指向 b 和 c 指向的值的指针放在 a 指向的列表中。如果然后设置 a[0] = d,则位置 0 的指针现在指向 d 所指向的任何内容。
See also the copy-module:?http://docs.python.org/library/copy.html
回答by abhiomkar
Shallow Copy:(copies chunks of memory from one location to another)
浅拷贝:(将内存块从一个位置复制到另一个位置)
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']
Deep Copy:(Copies object reference)
深层复制:(复制对象引用)
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']