2010-08-04 10 views
8

गहरा नीडिंत अजगर dicts के साथ कार्य करना पर उत्पन्न शब्दकोश चाबियाँ, मैं इस तरह इस तरह के एक डेटा संरचना में मान प्रदान करने में सक्षम होना चाहते हैं:मक्खी

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

कि mydict जाँच करने के लिए [कुंजी] आदि बिना वास्तव में एक नियम बनने के लिए सेट हैं, उदाहरण के लिए

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

उपनगरीय निर्माण का निर्माण फ्लाई पर होना चाहिए। कुछ समकक्ष अनुमति देने का सबसे शानदार तरीका क्या है - शायद मानक <type 'dict'> पर सजावटी का उपयोग करना?

+0

संबंधित प्रश्न: http://stackoverflow.com/questions/3122566/in-a-python-dict-of-dicts-how-do-you-emulate-perls-auto-vivification-behavior/3122575#3122575 – unutbu

उत्तर

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

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

आपको इसके साथ सावधान रहना होगा। 'डी ['ए'] = 2 डी ['ए'] ['बी'] = 2' असफल हो जाएगा। – unholysampler

+0

हां, लेकिन यह मेरे प्रश्न में निहित है - मैं मिश्रित प्रकार के डिब्बे और मूल्यों के लिए पूछ रहा हूं। – relet

+0

केस डी ['ए'] = 2 डी ['ए'] ['बी'] = 2 को हल करने के लिए, मैं कक्षा डी (dict) भी लिखूंगा: def __missing __ (स्वयं, कुंजी): मूल्य = स्वयं [कुंजी] = प्रकार (स्वयं)() वापसी मान डीईएफ़ __getitem __ (स्वयं, कुंजी): मूल्यों = dict .__ GetItem __ (स्वयं, कुंजी) अगर isinstance (मूल्यों, dict): मूल्यों = SafeDict (मान) अगर isinstance (मूल्यों, सूची): गणना में मैं के लिए , वी (मान): अगर isinstance (V, dict): मूल्यों [i] = SafeDict (v) वापसी को महत्व देता – user2346922

9

आप dict के लिए कुंजी के रूप में एक टपल इस्तेमाल कर सकते हैं और फिर आप subdictionaries के बारे में चिंता करने की जरूरत नहीं: वैकल्पिक रूप से

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

, यदि आप वास्तव में किसी कारण आप कर सकते थे के लिए subdictionaries की आवश्यकता है collections.defaultdict का उपयोग करें।

दो स्तरों के लिए यह स्पष्ट है:

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

तीन के लिए यह थोड़ा और अधिक जटिल है:

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

चार और अधिक स्तर पाठक के लिए एक व्यायाम के रूप में छोड़ दिया जाता है। :-)

+0

गजब का। मुझे खुशी है कि मैंने पूछा, अगर केवल इसलिए कि मुझे समझ में नहीं आता कि मैं इसे कैसे याद कर सकता हूं। :) – relet

+0

अच्छा जवाब। क्या आप इसे 'डिफॉल्टडिक्ट' के साथ कैसे कर सकते हैं? एक बार घोंसला आसान है: 'mydict = defaultdict (dict) '। लेकिन क्या दो बार घोंसले के लिए एक सुरुचिपूर्ण समाधान है? –

+0

@ जेलीबीन - बस तीन स्तर का समाधान जोड़ा गया; यह बहुत खराब नहीं है। –

2

मुझे डेव का उत्तर बेहतर पसंद है, लेकिन यहां एक विकल्प है।

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

यह निश्चित रूप से भीतरी डिफॉल्ट संग्रह को लागू करता है करने के लिए lambdas उपयोग करने के लिए सुंदर नहीं है, लेकिन जाहिरा तौर पर आवश्यक है।

+2

लैम्बडास कभी जरूरी नहीं हैं: आप हमेशा इसके बजाय नामित फ़ंक्शन का उपयोग कर सकते हैं। इस मामले में नामित फ़ंक्शन का उपयोग करने से कम से कम 'repr' का अर्थ' लैम्ब्डा 'से थोड़ा अधिक सार्थक होगा। – Duncan

संबंधित मुद्दे