Python中列表的值赋值与地址赋值有什么区别?

root = []
root[:] = [root, root, None]
root
>>> [[…], […], None]
root = []
root = [root, root, None]
root
>>> [[], [], None]

哪位 juju 可以深入浅出的解释一下,多谢多谢。
Python中列表的值赋值与地址赋值有什么区别?

7 回复

第一种情况的两个 root 是同一个 list 的引用。
第二种情况是创建了一个新的 list,元素是[root, root, None],这时候的 root 是[],然后把 root 指向这个对象,但是新 list 的前两个元素还是指向原来的那个[]。


简单说,就是 = 直接传地址(引用),copy()[:] 才真正复制数据。

看个例子就明白了:

# 地址赋值
list_a = [1, 2, 3]
list_b = list_a  # 这只是把 list_a 的地址给了 list_b
list_b[0] = 99
print(list_a)  # 输出 [99, 2, 3] !原列表也被改了

# 值赋值(浅拷贝)
list_c = [1, 2, 3]
list_d = list_c.copy()  # 或者 list_d = list_c[:]
list_d[0] = 99
print(list_c)  # 输出 [1, 2, 3] 原列表不变

关键点:

  • 地址赋值:两个变量指向同一个列表对象,改一个全变
  • 值赋值(浅拷贝):创建新列表,复制原列表的所有元素引用
  • 注意嵌套列表的情况,浅拷贝只复制第一层

简单说就是:想独立复制就用 copy()

root =[]
创建一个空列表对象,假设地址是 11111,root 变量存这个地址


root[:] = [root, root, None]
1.先执行[root, root, None] ,创建一个含三个元素的列表对象,地址假设为,22222,其中前两个 root 变量存的是 11111 这个地址,
2.执行 root[:],复制一个空列表对象,把这个新对象地址存在 root 变量里,因为是复制出来的是新对象,所以 root 里存的地址从 11111 变成 33333 (假设)
3.进行赋值 root 存的地址存 33333 变成 22222,也就是指向[root, root, None] ,而此时[root, root, None] 里面的 root 又指向[root, root, None] ,然后会无限循环下去

几种写法的比较:
root = [1, 2]
root[:] = [root, root, None]

root = [1, 2]
root[0:2] = [root, root, None]

root = [1, 2]
root = [root, root, None]

root = [1, 2]
root[0] = [root, root, None]

1、3、4 都是一样的,root 引用的还是同一个对象,但是对象里面的内容变了。2 则是 root 本身引用的对象变为了另一个对象。


b = [1,2]
id(b)
# Out[59]: 4459173000
b[0:2] = [b,b,None]
id(b)
# Out[61]: 4459173000

引用对象没变吧

#5

笔误,应该是 124,root 引用的还是同一个对象,但是对象里面的内容变了。3 则是 root 本身引用的对象变为了另一个对象。

回到顶部