[問題] list與list[:]差異

作者: ericrobin   2020-08-30 00:40:38
以前都沒注意到兩者不太一樣
直到我跑了下面這段碼
def subsets(self, nums):
def backtrack(start, end, tmp):
ans.append(tmp[:])
for i in range(start, end):
tmp.append(nums[i])
backtrack(i+1, end, tmp)
tmp.pop()
ans = []
backtrack(0, len(nums), [])
return ans
假如nums=[1,2,3]
照這段碼跑下去, tmp能夠隨著函數的呼叫持續變動,
最後ans 會返回1,2,3 [[],[1],[1,2],[1,2,3],[1,3],[2],[2,3],[3]]
然而如果第三行的tmp[:]改為tmp
最後只會是[[],[],[],[],[],[],[],[]]
不知道兩者間的差別在哪
而這差別除了在函數呼叫有影響外, 還有什麼時候要注意呢
以往沒特別打上[:]好像都沒出過事@@
用type看了一下都是<class 'list'>
我猜會不會tmp只是類似這list開頭的指標
而tmp[:]才是整段list的值?
作者: TuCH (謬客)   2020-08-30 02:11:00
是的 tmp只是指標 tmp[:] == tmp.copy()
作者: tsaiminghan (tsaiminghan)   2020-08-30 22:34:00
tmp[:]是淺複製(shallow copy)
作者: calvinvin (殘月)   2020-08-31 10:07:00
沒錯,對變數賦值時其實是將變數指向某段記憶體位址,例如a=[1,2,3], b=a, c=a的意思是創出一段值為[1,2,3]的記憶體位置,然後將a指向它,b、c則跟a也一樣指向它。透過a、b、c任一個變數使用method來修改[1,2,3]時,指向該處的a,b,c當然也就隨之而變。而賦值為list[:]時則是建立一個新的記憶體位址,其值為list[:],修改原本的list當然就不會影響到這新的、獨立的東西。所以你的程式碼將list[:]改成list後,跑的結果是將ans一直append上tmp,而這個tmp指向的值則是你最後將tmp給pop完的空list。以上是我非本科系自學新手的理解,若有觀念、名詞錯誤煩請大大不吝糾正,若是我自以為而沒回答的原po的問題,也先說抱歉@@

Links booklink

Contact Us: admin [ a t ] ucptt.com