Python 列表切片陷阱 引用 複製與深複製

2021-10-13 21:22:54 字數 1701 閱讀 2985

python 列表的切片和賦值操作很基礎,之前也遇到過一些坑,以為自己很懂了。但今天刷 codewars 時發現了乙個更大的坑,故在此記錄。

python 列表賦值:複製「值」還是「引用」?

很多入門 python 的人會犯這樣乙個錯誤:在賦值操作=中搞不清是賦了「值」還是「引用」。比如:

a =[1

,2,3

]b = ab[0

]=10# 更改列表 b 的第乙個元素,但 a 現在也被更改為了 [10, 2, 3]

他可能只想改變列表b,但實際上這樣也會改變列表a。

因為b實際上是列表a的另乙個引用,a和b是同乙個物件,id(a) == id(b),所以更改b也會更改a。這個應該大部分人都知道。所以正確的**應該使用切片來進行列表的複製:

'''

'''a =[1

,2,3

]b = a[:]

# 使用切片進行列表複製b[0

]=10# 此時 a 和 b 是兩個不同的物件

二維列表引發的思考:列表的本質

好的,現在我們確定切片能夠進行列表的複製。那我們就能心安理得地改動新的列表了嗎?請看二維列表(二維陣列):

a =[[

1,2,

3],[

4,5,

6]]b = a[:]

b[0][

0]=10

此時,a還是被改動了!

原因是,雖然id(a) == id(b)為false,a和b確實不是同乙個物件。但它們的元素都是同乙個物件——id(a[0]) == id(b[0])id(a[1]) == id(b[1])。因為列表裡儲存的是物件的引用!

列表 list 終究只是個容器。就像 tuple 本身是 immutable (不可變)的,但它只是容器,它可以儲存乙個可變物件,因此呈現出一種可以被改動的「假象」。例如:

'''

'''>>

> a =([

1],)

>>

> a[0]

[0]=

2>>

> a([

2],)

所以容器和它儲存的物件不能混為一談。所以對於這種二維列表,想要進行完全的複製,請直接使用copy.deepcopy()深度複製。

如果只想複製一部分(切片),那可以先複製再切片:

>>

>

import copy

>>

> a =[[

1,2,

3],[

4,5,

6],[

7,8,

9]]>>

> b = copy.deepcopy(a)[1

:]>>

> b[0]

[0]=

100>>

> a[[

1,2,

3],[

4,5,

6],[

7,8,

9]]>>

> b[[

100,5,

6],[

7,8,

9]]

此時修改b沒有影響到a。

python 切片 Python 列表切片

想必很多人都使用過列表的切片,通過切片可以從列表中獲取乙個或多個元素,但你真的了解切片?一 一般玩法 name a b c d e f g h name 0 2 獲取 0 2 中間的元素,不包括索引為 2 的元素 a b name 2 從 0 開始切,可省略 0 a b name 1 同樣地,切到最...

python 列表切片

a 0,1,2,3,4,5,6,7,8,9 print a 1 3 a 1 3 print a 3 a 3 print a 3 a 3 print a 1 7 2 a 1 7 2 步長為2 print a 1 a 1 從後往前遍歷 print a 7 1 2 a 7 1 2 從後往前遍歷,步長為2 ...

python列表切片

基本含義 從第i位索引起,向右取到後n位元素為止,按m間隔過濾 基本格式 i i n m i 是切片的起始索引值,為列表首位時可省略 i n 是切片的結束位置,為列表末位時可省略 m 可以不提供,預設值是1,不允許為0,當m為負數時,列表翻轉。注意 這些值都可以大於列表長度,不會報越界。正數索引,預...