2011-11-01 8 views
15

collections.defaultdict thật tuyệt vời. Đặc biệt kết hợp với lambda:Sử dụng khóa trong collections.defaultdict

>>> import collections 
>>> a = collections.defaultdict(lambda : [None,None]) 
>>> a['foo'] 
[None, None] 

Có cách nào để sử dụng phím nhất định (ví dụ 'foo') trong lambda? Ví dụ: (không hoạt động):

>>> a = collections.defaultdict(lambda : [None]*key) 
>>> a[1] 
[None] 
>>> a[2] 
[None, None] 
>>> a 
defaultdict(<function <lambda> at 0x02984170>, {1: [None], 2: [None, None]}) 

Trả lời

30

Bạn có thể muốn __missing__ được gọi là trên dict bất cứ khi nào bạn cố gắng truy cập vào một mục không có mặt trong dict; vani __missing__ đặt ra một ngoại lệ, nhưng bạn có thể làm bất cứ điều gì bạn thích trong một lớp con:

class A(dict): 
    def __missing__(self, key): 
     value = self[key] = [None] * key 
     return value 
+0

không biết về phương pháp kỳ diệu này trước đây, :), tuyệt vời –

1

Thao tác này sẽ hoạt động như được yêu cầu, bạn cần phải khởi chạy với cuộc gọi mặc định và sau đó không sử dụng). Nó có thể có thể được cố định bằng cách ghi đè một số phương thức khác.

class NoneDict(collections.defaultdict): 
    def __setitem__(self, key, value): 
     super(NoneDict, self).__setitem__(key, key*[None]) 
2

Kết hợp các câu trả lời từ SingleNegationEliminationrplnt, và the defaultdict documentation, tôi sử dụng các giải pháp sau đây.

import collections 
class KeyBasedDefaultDict(collections.defaultdict): 
    def __missing__(self, key): 
     if self.default_factory is None: 
      raise KeyError(key) 
     self[key] = self.default_factory(key) 
     return self[key] 

Phần thân của phương thức có thể chỉ là return self.default_factory(key), nhưng mã phụ đảm bảo sao chép tất cả hành vi mặc định.

Cách sử dụng như mô tả trong câu hỏi:

d = KeyBasedDefaultDict(lambda key: [None] * key) 
d[1] 
> [None] 
d[2] 
> [None, None]