简体   繁体   English

修改 Python 列表的一部分时会发生什么

[英]What is happening when you modify a slice of a python list

The following code creates a list, assigns a slice of the list to a new variable, and then modifies this slice using the new variable B .以下代码创建一个列表,将列表的一个切片分配给一个新变量,然后使用新变量B修改该切片。 The memory addresses of the elements of A and B are the same, but modifying B does not affect A. What am I missing here? AB的元素的内存地址是一样的,但是修改 B 不会影响 A。我在这里遗漏了什么?

def printAddresses(A):
    for i in range(len(A)):
        print(f"memory address of list element {i}: {hex(id(A[i]))}")
    print("\n\n\n")


A = list(range(5))
B = A[:]
print("addresses of elements of A")
printAddresses(A)
print("addresses of elements of B")
printAddresses(B)

for i in range(len(B)):
    B[i]=12345
print("A: ", A)
print("B: ", B)

Output:输出:

addresses of elements of A
memory address of list element 0: 0x10821e470
memory address of list element 1: 0x10821e490
memory address of list element 2: 0x10821e4b0
memory address of list element 3: 0x10821e4d0
memory address of list element 4: 0x10821e4f0


addresses of elements of B
memory address of list element 0: 0x10821e470
memory address of list element 1: 0x10821e490
memory address of list element 2: 0x10821e4b0
memory address of list element 3: 0x10821e4d0
memory address of list element 4: 0x10821e4f0


A:  [0, 1, 2, 3, 4]
B:  [12345, 12345, 12345, 12345, 12345]

The memory addresses of the data held by the lists are the same, since each list contains references to the same objects.列表保存的数据的内存地址是相同的,因为每个列表都包含对相同对象的引用。 A slice creates a shallow-copy, which means that the structure of the list is copied, but the objects it contains aren't .切片创建浅拷贝,这意味着列表的结构被复制,但它包含的对象不是 A and B both contain references to the same objects at the same time. AB同时包含对相同对象的引用。

If you check the address of the structures themselves though, you'll see the difference:但是,如果您检查结构本身的地址,您会看到不同之处:

def printAddresses(A):
    print(hex(id(A)))  # Print list address
    for i in range(len(A)):
        print(f"memory address of list element {i}: {hex(id(A[i]))}")
    print("\n\n\n")

Then, when run:然后,运行时:

addresses of elements of A
0x420cd88
memory address of list element 0: 0x63abf7a0
memory address of list element 1: 0x63abf7b0
memory address of list element 2: 0x63abf7c0
memory address of list element 3: 0x63abf7d0
memory address of list element 4: 0x63abf7e0
addresses of elements of B
0x195d0a8
memory address of list element 0: 0x63abf7a0
memory address of list element 1: 0x63abf7b0
memory address of list element 2: 0x63abf7c0
memory address of list element 3: 0x63abf7d0
memory address of list element 4: 0x63abf7e0
A:  [0, 1, 2, 3, 4]
B:  [12345, 12345, 12345, 12345, 12345]

Note how 0x420cd88 != 0x195d0a8 .请注意如何0x420cd88 != 0x195d0a8 The objects held are literally the same, but the structures holding them are different.持有的对象实际上是相同的,但持有它们的结构不同。

I think a key here is that B[i]=12345 does not modify the object that was previously at i .我认为这里的一个关键是B[i]=12345不会修改之前位于i的对象。 B[0]=12345 removes the 0 from the list, then puts a 12345 in its place. B[0]=12345从列表中删除0 ,然后在其位置放置一个12345 That does not change the 0 .这不会改变0

It's the same as how this:这与以下方式相同:

n = 0
list_a = [n]
list_b = [n]  # Same object in both lists

list_a[0] = 9
print(list_a, list_b)

Prints [9] [0] .打印[9] [0] This takes the 0 out of list_a , and puts a 9 in its place.list_a取出0 ,并在其位置放置一个9 The 0 is not modified. 0未修改。 Taking an orange of a box and putting an apple in its place does not modify the orange.取一个盒子里的橙子并在它的位置上放一个苹果不会改变橙子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM