2010-08-04 36 views
8

Làm việc với dicts python lồng nhau sâu sắc, tôi muốn để có thể gán giá trị trong một cấu trúc như vậy dữ liệu như thế này:phím từ điển Tạo on the fly

mydict[key][subkey][subkey2]="value" 

mà không cần phải kiểm tra mydict rằng [key] vv thực sự được đặt thành một dict, ví dụ sử dụng

if not key in mydict: mydict[key]={} 

Việc tạo các từ điển sẽ xảy ra khi đang di chuyển. Cách thanh lịch nhất để cho phép cái gì đó tương đương - có thể sử dụng trang trí theo tiêu chuẩn <type 'dict'>?

+0

Câu hỏi liên quan: http://stackoverflow.com/questions/3122566/in-a-python-dict-of-dicts-how-do-you-emulate-perls-auto-vivification-behavior/3122575#3122575 – unutbu

Trả lời

19
class D(dict): 
    def __missing__(self, key): 
     self[key] = D() 
     return self[key] 

d = D() 
d['a']['b']['c'] = 3 
+1

Bạn phải cẩn thận với điều này. 'd ['a'] = 2 d ['a'] ['b'] = 2' sẽ thất bại. – unholysampler

+0

Có, nhưng điều đó được ngụ ý trong câu hỏi của tôi - tôi yêu cầu một loại hỗn hợp các giá trị và giá trị. – relet

+0

Để giải quyết trường hợp d ['a'] = 2 d ['a'] ['b'] = 2, tôi thậm chí sẽ viết lớp D (dict): def __missing __ (self, key): value = self [key] = loại (tự)() giá trị trả về def __getitem __ (tự, phím): giá trị = dict .__ GetItem __ (tự, key) nếu isinstance (giá trị, dict): giá trị = SafeDict (giá trị) nếu isinstance (giá trị, danh sách): cho i, v trong liệt kê (giá trị): nếu isinstance (v, dict): giá trị [i] = SafeDict (v) giá trị trả lại – user2346922

9

Bạn có thể sử dụng một tuple là chìa khóa cho dict và sau đó bạn không cần phải lo lắng về subdictionaries tại tất cả:

mydict[(key,subkey,subkey2)] = "value" 

Ngoài ra, nếu bạn thực sự cần phải có subdictionaries vì ​​một lý do bạn có thể sử dụng collections.defaultdict.

Đối với hai cấp độ này là đơn giản:

>>> from collections import defaultdict 
>>> d = defaultdict(dict) 
>>> d['key']['subkey'] = 'value' 
>>> d['key']['subkey'] 
'value' 

Đối với ba nó hơi phức tạp hơn:

>>> d = defaultdict(lambda: defaultdict(dict)) 
>>> d['key']['subkey']['subkey2'] = 'value' 
>>> d['key']['subkey']['subkey2'] 
'value' 

Four và nhiều cấp độ còn lại như một bài tập cho người đọc. :-)

+0

Kinh ngạc. Tôi vui vì tôi đã hỏi, nếu chỉ vì tôi không hiểu làm thế nào tôi có thể bỏ lỡ điều này. :) – relet

+0

Câu trả lời hay. Bạn có thể cung cấp cách thực hiện nó bằng 'defaultdict' không? Làm tổ một lần rất dễ dàng: 'mydict = defaultdict (dict)'. Nhưng liệu có một giải pháp thanh lịch để làm tổ hai lần? –

+0

@ jellybean - chỉ cần thêm giải pháp ba cấp độ; nó không quá tệ. –

2

Tôi thích câu trả lời của Dave tốt hơn, nhưng đây là giải pháp thay thế.

from collections import defaultdict 
d = defaultdict(lambda : defaultdict(int)) 
>>> d['a']['b'] += 1 
>>> d 
defaultdict(<function <lambda> at 0x652f0>, {'a': defaultdict(<type 'int'>, {'b': 1})}) 
>>> d['a']['b'] 
1 

http://tumble.philadams.net/post/85269428/python-nested-defaultdicts

Đó chắc chắn không đẹp phải sử dụng lambdas để thực hiện các bộ sưu tập defaulted bên trong, nhưng dường như cần thiết.

+2

Lambdas không bao giờ cần thiết: bạn luôn có thể sử dụng hàm được đặt tên thay thế. Trong trường hợp này, việc sử dụng hàm được đặt tên ít nhất có nghĩa là 'repr' có cái gì đó có ý nghĩa hơn một chút so với' lambda'. – Duncan

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