Something haunts me in Python
@1: 在查看"The Python Library Reference"(https://docs.python.org/2/library/stdtypes.html#sequence-types-str-unicode-list-tuple-bytearray-buffer-xrange)
的时候发现了这样的一段代码:
代码1:
>>> lists = [[]] * 3 >>> lists [[], [], []] >>> lists[0].append(3) >>> lists
执行完lists[0].append(3)之后,程序将输出什么结果? [[3], [0], [0]]?
正确答案是[[3], [3], [3]],让我们来看看Reference上的解释:
This often haunts new Python programmers. What has happened is that [[]] is a one-element list containing
an empty list, so all three elements of [[]] * 3 are (pointers to) this single empty list. Modifying any of the elements
of lists modifies this single list. You can create a list of different lists this way:
代码2:
>>> lists = [[] for i in range(3)] >>> lists[0].append(3) # 此时lists为[[3], [], []] >>> lists[1].append(5) >>> lists[2].append(7) >>> lists [[3], [5], [7]]
补充:代码1中lists的三个元素都指向同一个空list,是因为:s * n, n * s --- n shallow copies of s concatenated,
即Python中的*运算采用的是浅复制。
@2: Slicing & Slice Assignment(http://stackoverflow.com/questions/10623302/how-assignment-works-with-python-list-slice/10623352#10623352)
1. slicing:
b = a[0:2]
This makes a copy of the slice of a and assigns it to b.
2. slice assignment:
a[0:2] = b
This replaces the slice of a with the contents of b.
Although the syntax is similar (I imagine by design!), these are two different operations.
@3: 针对上面silce assignment的例子进行进一步分析:
>>> a = [1, 4, 3] >>> b = [6, 7] >>> a[1:3] = b >>> a [1, 6, 7] >>> b [6, 7] >>> a[1] = 0 >>> a [1, 0, 7]
此时b的值是多少?
>>> b [6, 7] >>>
让我们继续:
代码1:
>>> a[0:3] = b #长度不同,也允许 >>> a [6, 7] >>> b [6, 7] >>> a[1] = 1 #这种情况, 改变a不会影响b >>> a [6, 1] >>> b [6, 7] >>> b[1] = 8 #这种情况, 改变b不会影响a >>> b [6, 8] >>> a [6, 1]
代码2:
>>> b = [6, 7] >>> c = b >>> c [6, 7] >>> b[0] = 0 >>> b [0, 7] >>> c [0, 7] >>> c[0] = 10 >>> b [10, 7] >>> c [10, 7]
比较代码1和代码2结果的不同,进一步理解slice assignment。
代码3: slicing
>>> a = [1, 2, 3, 4] >>> b = a[:2] >>> a [1, 2, 3, 4] >>> b [1, 2] >>> b[0] = 9 >>> b [9, 2] >>> a [1, 2, 3, 4]