2013-12-10 83 views
1

我需要從函數內的列表中刪除前N個元素,我希望修改原始列表。在Python中執行此操作的簡明方法是什麼?如何在Python中切片列表而不復制參考?

使用slice不起作用,因爲slice操作返回對列表的單獨引用。在這個例子中,我想調用函數後pkt[3,4,5]

>>>> def process_packet(packet, num_bytes): 
     # ... 
     packet = packet[num_bytes:len(packet)] 
     print packet 

>>> pkt = [1,2,3,4,5] 
>>> process_packet(pkt, 2) 
[3, 4, 5] 
>>> print pkt 
[1, 2, 3, 4, 5] 
+2

'packet [:] = packet [num_bytes:]' –

回答

4

使用片內的符號刪除切片:

def process_packet(packet, num_bytes): 
    packet[:] = packet[num_bytes:len(packet)] 
    print packet 

>>> pkt = [1,2,3,4,5] 
>>> process_packet(pkt, 2) 
[3, 4, 5] 
>>> print pkt 
[3, 4, 5] 

注只有在packet是一個列表或兼容的迭代器時纔有效。名單的初始和最終長度可能不同,(大或小,或者反之亦然)。

1

在函數結束時添加return packet

當你調用函數調用它是這樣的:pkt = process_packet(pkt,2)

+0

OP不想創建新列表,但我不確定列表突變是否是pythonic方式。 – MxyL

+0

@MxyL他們沒有明確表示他們不想要一個新的列表 - 更多的是他們想要更新原件......這是以一種循環的方式:)(無論如何給出了這個例子 - 還有其他的引用列表 - 它會使我的快速回復失效) –

+0

@JonClements你是對的,我認爲「不起作用,返回一個單獨的參考」部分暗示「我們不想複製」 – MxyL

7

只需使用del在地方:)

>>> def process_packet(packet, num_bytes): 
...  del packet[num_bytes:len(packet)] 
... 
>>> a = range(10) 
>>> process_packet(a,4) 
>>> a 
[0, 1, 2, 3] 
+0

隨着文檔字符串說「這將修改你的輸入清單」或類似的...無論如何微妙。我還會考慮將名稱更改爲'alter_'或類似的名稱以使其更清晰...... –

+0

@JonClements對,這是一個很好的建議。我只是從上面的代碼中複製了最基本的行(&名字)。希望他已經在他的生產代碼中這樣做了。 :) – SuperSaiyan

+1

很高興瞭解'del'。在這種情況下'del packet [0:num_bytes]'將匹配原始問題中的功能。 – mksuth

0

您可以使用從集合模塊的次deque和popleft NUM_BYTES,或者創建修改self.pkt類,或者最簡單的方法是這樣的:

def process_packet(pkt, num): 
    return pkt[num:] 

pkt = process_packet(pkt, 2) 

只返回數據包,並重新分配它。這可能是你看到處理這種邏輯最多的東西。