2012-02-20 48 views
5

我試圖保留一個打開文件的字典,將數據分割成單個文件。當我從字典中請求文件時,如果密鑰不在那裏,我希望它被打開。但是,它看起來不像我可以使用lambda作爲默認值。是否可以使用lambda作爲字典默認值?

例如

files = {} 
for row in data: 
    f = files.get(row.field1, lambda: open(row.field1, 'w')) 
    f.write('stuff...') 

這不起作用,因爲f被設置爲函數而不是結果。使用上述語法的setdefault也不起作用。有什麼我可以除了這個做:

f = files.get(row.field1) 
if not f: 
    f = files[row.field1] = open(row.field1, 'w') 

回答

7

這個用例是一個defaultdict太複雜了,這就是爲什麼我不相信這樣的事情在Python STDLIB存在。但是,您可以輕鬆地編寫一個通用的「擴展」 defaultdict自己,這傳遞缺少鍵回調:

from collections import defaultdict 

class BetterDefaultDict(defaultdict): 
    def __missing__(self, key): 
    return self.setdefault(key, self.default_factory(key)) 

用法:

>>> files = BetterDefaultDict(lambda key: open(key, 'w')) 
>>> files['/tmp/test.py'] 
<open file '/tmp/test.py', mode 'w' at 0x7ff552ad6db0> 

這工作在Python 2.7+,不知道舊版本:)另外,不要忘記再次關閉這些文件:

finally: 
    for f in files.values(): f.close() 
2

你可以換一開始和開放的一類對象的__getitem__()很容易地 - 李的東西柯:

class FileCache(object): 
    def __init__(self): 
     self.map = {} 

    def __getitem__(self,key): 
     if key not in self.map:    
      self.map[key] = open(key,'w') 
     return self.map.key 
1

另一種選擇的子類,它應該做你需要的東西:

class LambdaDefaultDict(dict): 

    def get(self, key, default=None): 
     try: 
      return self[key] 
     except KeyError: 
      return default() 

    def setdefault(self, key, default=None): 
     if not self.has_key(key): 
      self[key] = default() if default else None 
     return self[key] 

或者更一般 - 允許的值或調用表達式的默認值:

class CallableDefaultDict(dict): 

    def get(self, key, default=None): 
     try: 
      return self[key] 
     except KeyError: 
      return default() if callable(default) else default 

    def setdefault(self, key, default=None): 
     if not self.has_key(key): 
      self[key] = default() if callable(default) else default 
     return self[key] 
1

您可以使用收藏模塊中的defaultdict

class FileCache(collections.defaultdict): 
    def __missing__(self, key): 
    fo = open(key, 'w') 
    self[key] = fo 
    return fo 

雖然它可能會更好只是做

files = {} 
def get_file(f): 
    fo = files.get(f) 
    if fo is None: 
    fo = open(f, 'w') 
    files[f] = fo 
    return fo 

for row in data: 
    f = get_file(row.field1) 
    f.write('stuff...') 
1

這是確切的原因dict[key]語法引發KeyError

files = {} 
for row in data: 
    f = files.get(row.field1, lambda: open(row.field1, 'w')) 
    f.write('stuff...') 

應該變成:

files = {} 
for row in data: 
    try: f = files[row.field1] 
    except KeyError: f = open(row.field1, 'w') 
    f.write('stuff...') 
+1

的get()不提高如果找不到該項目,則會出現關鍵錯誤。 []符號。例如文件[關鍵] – Jacob 2012-02-20 21:56:25

相關問題