2017-10-12 99 views
0

是否可以將(移動)指針傳遞給列表中的某個列表,並將其開始放入Python中的某個函數中?將列表指針傳遞給一個函數而不是列表

我有一個遞歸函數在列表的一部分工作。該列表本身沒有改變,只有指向它的「起點」的指針。我遇到的問題是,長列表導致內存溢出導致代碼死機。

下面是代碼:

def trim(l): 
    print("list len= ", len(l)) 
    if len(l)!= 1: 
     trim(l[1:]) 
    else: 
     print("done") 

上面的例子是人爲的,我實際的代碼做不同的東西,不僅僅是修剪列表中,但它也有一個移動的開始指針。一個100萬個整數的列表在10G RAM機器上耗盡內存。

歡迎任何想法。

+3

Python並不指針。您可以嘗試傳遞索引而不是創建副本的切片。你也可以考慮使用'numpy',它提供了面向對象的原始數組,其中切片創建視圖,而不是副本。還有內置的「數組」模塊,它提供空間有效的基本數組類型的原始數組。這兩種陣列方法都應該提供數量級的節省空間。一百萬64位整數約爲8兆字節 –

+1

您可能會發現['deque'](https://docs.python.org/3.6/library/collections.html#collections.deque)數據結構有用。您可以使用'l.popleft()'從deque頭部刪除一個元素,而不是傳遞一個slice(這是所有元素的淺表副本)。當'l'是一個列表時,這不會導致'l.pop(0)'的複製成本。 – trentcl

回答

2

難道你不只是傳遞索引而不是傳遞整個新列表?

因此,您可以撥打trim(l, 0),然後根據列表長度檢查索引,然後在需要時調用trim(l, 1)

def trim(l, idx): 
    print("list len = ", (len(l) - idx)) 
    if idx < (len(x) - 1): 
     trim(l, idx + 1) 
    else: 
     print("done") 
2

如果您正在編寫一個非尾調用遞歸函數來遍歷列表,那麼您的問題更可能是堆棧溢出或與堆棧大小相關的內存不足錯誤。

我建議用一個整型指針和一個for-loop重寫它,因爲Python似乎沒有tail-call優化。

這裏有一個猜測,你可能會想要做什麼:

x = [0,0,0,0,0,1,2,3,4] 

def trim_leading_zero(l): 
    the_len = len(l) 
    start_i = 0 
    for i in xrange(the_len): 
    if l[i] != 0: 
     return l[i:] 

>>> trim_leading_zero(x) 
[1, 2, 3, 4] 

這不是從你的代碼是什麼的意思實際上做明確。如果你試圖返回一個序列,那麼你可能想看看Generators,它不需要在內存中保存整個序列。

0

在處理大型數據處理,使用發電機,而不是常規的迭代器。

def trim(l): 
    print("list len= ", len(l)) 
    pointer = 0 
    if len(l)!= 1: 
     yield l[pointer:] 
     pointer += 1 
    else: 
     print("done") 

x = [1, 2, 3, 4, 5, 6, 7, 8, 9] 

for i in trim(x): 
    print i 

# [1, 2, 3, 4, 5, 6, 7, 8, 9] 

發電機將在同一時間產生一個項目,讓你做任何你需要它,迴避處理之前,先創建整個列表。如果你想從中得到一個列表,你可以簡單地做list(trim(x))

還有的yieldgenerators這裏偉大的解釋 - What does the yield keyword do