2012-02-20 19 views
5

Tôi đang cố giữ từ điển các tệp đang mở để tách dữ liệu thành các tệp riêng lẻ. Khi tôi yêu cầu một tập tin từ từ điển tôi muốn nó được mở nếu khóa không có ở đó. Tuy nhiên, có vẻ như tôi không thể sử dụng lambda làm mặc định.có thể sử dụng lambda làm từ điển mặc định không?

ví dụ:

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

Điều này không có tác dụng vì f được đặt thành hàm thay vì kết quả. setdefault sử dụng cú pháp ở trên cũng không hoạt động. Có bất cứ điều gì tôi có thể làm ngoài này:

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

Trả lời

7

trường hợp sử dụng này là quá phức tạp đối với một defaultdict, đó là lý do tôi không tin rằng một cái gì đó như thế này tồn tại trong stdlib Python. Bạn có thể tuy nhiên dễ dàng viết một generic "mở rộng" defaultdict chính mình, mà đi chìa khóa thiếu để gọi lại:

from collections import defaultdict 

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

Cách sử dụng:

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

này hoạt động bằng Python 2.7+, không biết về phiên bản cũ :) Ngoài ra, đừng quên để đóng các tập tin một lần nữa:

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

Bạn có thể quấn get-và-mở trong __getitem__() khá dễ dàng một đối tượng lớp của - một cái gì đó li ke:

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

Một tùy chọn khác cho một lớp con rằng nên làm những gì bạn cần:

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] 

Hoặc, có lẽ tổng quát hơn - để cho phép giá trị mặc định có giá trị hoặc biểu thức callable:

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

Bạn có thể sử dụng defaultdict từ mô-đun bộ sưu tập

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

Mặc dù nó có thể là tốt hơn để chỉ làm

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

Đây là lý do chính xác tại sao dict[key] cú pháp tăng KeyError:

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

nên trở thành:

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

get() không làm tăng một lỗi chính nếu không tìm thấy mục đó. Ký hiệu []. ví dụ. tệp [key] – Jacob

Các vấn đề liên quan