2010-07-29 17 views
9

मैं क्षमा शब्दकोश (एक है कि एक डिफ़ॉल्ट मान है, तो एक KeyError उठाया है देता है) बनाने के लिए कैसे सोच रहा हूँ।एक क्षमा शब्दकोश

निम्न कोड उदाहरण में मैं एक KeyError मिलेगा; उदाहरण के लिए

a = {'one':1,'two':2} 
print a['three'] 

एक प्राप्त करने के क्रम में मुझे 1. अपवाद पकड़ना या उपयोग करना है।

मैं चाहते हैं कि ऐसा करने के लिए मेरी शब्दकोश के साथ ...

+2

'collections.defaultdict' आपकी बैटरी-शामिल समाधान है। –

+1

प्रश्न शीर्षक के लिए +1 –

उत्तर

22
import collections 
a = collections.defaultdict(lambda: 3) 
a.update({'one':1,'two':2}) 
print a['three'] 

का उत्सर्जन करता है 3 के रूप में आवश्यक है करने के लिए नहीं है। तुम भी अपने आप को dict उपवर्ग सकता है और __missing__ ओवरराइड, लेकिन वह ज्यादा मतलब नहीं है जब defaultdict व्यवहार (सटीक लापता महत्वपूर्ण यह है कि ऊपर देखा जा रहा है अनदेखी) आप इतनी अच्छी तरह से सूट ...

संपादित ... जब तक, यानी, आप a के बारे में चिंतित हैं, जब भी आप एक लापता कुंजी (जो defaultdict के अर्थशास्त्र का हिस्सा है) को देखते हैं और धीमे व्यवहार को प्राप्त करते हैं लेकिन कुछ स्मृति को बचाते हैं। उदाहरण के लिए, स्मृति के मामले में ...:

>>> import sys 
>>> a = collections.defaultdict(lambda: 'blah') 
>>> print len(a), sys.getsizeof(a) 
0 140 
>>> for i in xrange(99): _ = a[i] 
... 
>>> print len(a), sys.getsizeof(a) 
99 6284 

... defaultdict, मूल रूप से खाली है, अब 99 पहले से लापता कुंजी है कि हम ऊपर देखा है, और 6284 बाइट्स (बनाम 140 बाइट्स लेता है यह खाली होने पर लिया गया)।

वैकल्पिक दृष्टिकोण ...:

>>> class mydict(dict): 
... def __missing__(self, key): return 3 
... 
>>> a = mydict() 
>>> print len(a), sys.getsizeof(a) 
0 140 
>>> for i in xrange(99): _ = a[i] 
... 
>>> print len(a), sys.getsizeof(a) 
0 140 

... पूरी तरह से इस स्मृति ओवरहेड सुरक्षित रहता है, जैसा कि आप देख सकते है। ,

$ python -mtimeit -s'import collections; a=collections.defaultdict(int); r=xrange(99)' 'for i in r: _=a[i]' 
100000 loops, best of 3: 14.9 usec per loop 

$ python -mtimeit -s'class mydict(dict): 
> def __missing__(self, key): return 0 
> ' -s'a=mydict(); r=xrange(99)' 'for i in r: _=a[i]' 
10000 loops, best of 3: 92.9 usec per loop 

defaultdict के बाद से (पहले-लापता) देखने पर कुंजी कहते हैं यह बहुत तेजी से जब इस तरह के एक महत्वपूर्ण अगले ऊपर देखा है mydict (जो __missing__ ओवरराइड करता है कि से बचने के लिए, जबकि हो जाता है,: बेशक, प्रदर्शन एक और मुद्दा है इसके अलावा) हर बार "लापता कुंजी लुकअप ओवरहेड" का भुगतान करता है।

आप या तो इस मुद्दे (बनाम स्मृति पदचिह्न प्रदर्शन) के बारे में परवाह है या नहीं पूरी तरह से निश्चित रूप से, अपने विशिष्ट उपयोग के पर निर्भर करता है। यह किसी भी मामले में एक अच्छा विचार तालमेल के बारे में पता होना करने के लिए है -)

+3

चेतावनी: जब भी यह किसी दिए गए कुंजी के लिए डिफ़ॉल्ट मान देता है तो डिफॉल्टडिक्ट स्वयं में एक नया आइटम डालता है। इससे संभावित लेखन कार्यों में पढ़ने के संचालन को बदल दिया जाता है, और इसका मतलब है कि बहुत सारी गायब कुंजियों को देखकर यह तेजी से बढ़ने का कारण बन जाएगा। http://docs.python.org/library/collections.html#collections.defaultdict.__missing__ –

+0

@ Forest, अच्छा बिंदु! मुझे तदनुसार संपादित करने दें। –

+0

उत्कृष्ट पोस्ट! अंतिम पैराग्राफ में आपका दूसरा उदाहरण आपके उदाहरण से संबंधित प्रतीत नहीं होता है क्योंकि आप कभी भी एक ही कुंजी का दो बार उपयोग नहीं करते हैं। तो ऐसा लगता है कि डिफ़ॉल्ट डिक्शनरी तेज है, भले ही आप कभी भी एक कुंजी दोहराएं और तेज़ न करें। क्या वह सही है? –

7

नया संस्करण 2.5 में: dict का एक उपवर्ग एक विधि __missing __() को परिभाषित करता है, तो यदि कुंजी कुंजी नहीं है वर्तमान, डी [कुंजी] आपरेशन तर्क के रूप में कुंजी कुंजी के साथ कि विधि कहता है। डी [कुंजी] आपरेशन तो रिटर्न या को जन्म देती है जो कुछ भी लौट आए या __missing __ (key) फोन करता है, तो कुंजी मौजूद नहीं है द्वारा उठाया जाता है। कोई अन्य संचालन या विधियां प्रारंभ __missing __()। यदि __missing __() परिभाषित नहीं किया गया है, तो KeyError उठाया गया है। __missing __() एक विधि होनी चाहिए; यह एक आवृत्ति चर नहीं हो सकता है। उदाहरण के लिए, collections.defaultdict देखें।

http://docs.python.org/library/stdtypes.html

3

आप शायद एक defaultdict का उपयोग करना चाहेंगे

from collections import defaultdict 
def default(): return 'Default Value' 
d = defaultdict(default) 
print(d['?']) 

समारोह है कि निर्माता को पारित कर दिया है करने के लिए वर्ग क्या कहता है (यह कम से कम python2.5 मेरा मानना ​​है कि आवश्यकता है) एक डिफ़ॉल्ट मान के रूप में वापसी करें। अतिरिक्त उदाहरणों के लिए the documentation देखें।

5

यहाँ dict उपवर्ग के लिए कैसे के रूप में NullUserException ने सुझाव दिया है

>>> class forgiving_dict(dict): 
...  def __missing__(self, key): 
...   return 3 
... 
>>> a = forgiving_dict() 
>>> a.update({'one':1,'two':2}) 
>>> print a['three'] 
3 

इस उत्तर और एलेक्स के बीच एक बड़ा अंतर लापता कुंजी नहीं शब्दकोश

>>> print a 
{'two': 2, 'one': 1} 

को जोड़ा गया है वह यह है कि कौन सा यदि आप बहुत सारी यादों की उम्मीद करते हैं तो

0

कभी-कभी आप क्या करते हैं सहयोगी चाहते हैं .setdefault() जो बहुत सहज नहीं है, लेकिन यह एक तरीका है कि "निर्दिष्ट कुंजी देता है, यदि यह अस्तित्व में नहीं है, तो इस मान को उस कुंजी को सेट करें"।

collection = {} 
for elem in mylist: 
    key = key_from_elem(elem) 
    collection.setdefault(key, []).append(elem) 

यह हमें की तरह एक शब्दकोश बनाने के लिए अनुमति देगा:: वहाँ एक कुंजी है, तो पहले से ही वहाँ देखने के लिए एक बदसूरत नियंत्रण रखने के बिना {'key1':[elem1, elem3], 'key2':[elem3]} और

यहाँ setdefault() का एक उदाहरण अच्छे प्रभाव के लिए इस्तेमाल किया जा रहा है इसके लिए एक सूची बनाना।

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