2017-10-19 36 views
1

我試圖讓我的程序更有效一些。我有一個包含大量數據序列的特定模塊。目前,它是代表序列名稱(鍵)和多個生成器函數作爲值附加在一起的鍵值對的字典。例如:僅在調用字典密鑰時生成數據

sequences = { 
    'One' = make_items(100000) + make_other_items(20) 
    'Two' = make_items(9393) 
    } 

現在我們假設make_items生成n個隨機字符串,n是作爲參數提供的整數。隨着序列數量的增加,如果我只需要在程序執行過程中將一個項目的值存儲在字典中,就會嚴重影響處理和內存。如果sequences位於模塊的全局名稱空間中,則將在導入模塊並將其存儲在內存中時加載所有內容。如果我把字典放在一個函數中,然後返回我調用的值,內存問題就解決了,但是當調用wrapper函數時它仍然會計算字典中每個項的每個值 - 也不是那麼高效。

我的想法是爲全局名稱空間中的每個值創建一個函數,然後在調用一個項目後使用映射器字典實際運行該函數。我想知道這是否是最簡單的方法,因爲它增加了代碼的複雜性,並且必須確保變量和字符串在多個位置拼寫正確。

sequences = [ 
    'Sequence One', 
    'Sequence Two', 
    'Sequence Three', 

def SEQUENCE_ONE(): 
    data = make_items(100000) + make_other_items(20) 
    return data 

def SEQUENCE_TWO(): 
    data = make_items(9393) 
    return data 

def SEQUENCE_THREE(): 
    data = make_other_items(4) 
    return data 

def mapper(name): 
    map = { 
     'Sequence One': SEQUENCE_ONE, 
     'Sequence Two': SEQUENCE_TWO, 
     'Sequence Three': SEQUENCE_THREE 
     } 
    data = map[name]() 
    return name, data 

這是最乾淨,最簡單的解決方案,還是有更好的方法來實現動態數據生成?

+2

你不能這樣做,因爲Python首先評估右邊的表達式。然而,你可以構造一些* lazy dictionary *並傳遞它的函數而不是實際的值。這些功能會在需要時進行計算。 –

+0

這聽起來像是[cached-property](https://pypi.python.org/pypi/cached-property)的一個很好的用例。 – wim

+1

[yield/generators](https://docs.python.org/2.7/reference/expressions.html#yieldexpr)會有幫助嗎? – Luce

回答

1

的提出爲你通過繼承defaultdict一個更Python的選擇:

from collections import defaultdict 

def make_items(n): 
    print('making {} items...'.format(n)) 
    return range(n) 

class LazyDict(defaultdict): 
    def __missing__(self, k): 
     self[k] = make_items(k) 
     return self[k] 

sequences = LazyDict() 

它只會產生在第一次使用的值:

>>> sequences = LazyDict() 
>>> sequences[10] 
making 10 items... 
range(0, 10) 
>>> sequences[10] 
range(0, 10) 

你可以很容易適應的__missing__實施提高KeyError如果密鑰不在{'Sequence One', 'Sequence Two', 'Sequence Three'}

+0

這看起來像它幾乎會工作 - 但我不知道如何適應我的使用情況。如果您看一下我的示例代碼,那麼每個序列都會按照該序列名稱的不同順序使用不同的生成器函數 - 因此每個序列名稱都需要定義該序列所需的確切函數調用。這可以適應嗎? – iceblueorbitz

+0

是的,所以你可以從'__missing__'中調用函數。試試吧,我會把這部分留給你。 – wim