2011-02-15 22 views
6

में डुप्लिकेट कुंजी अगर त्रुटि में वृद्धि कैसे करें यदि उपयोगकर्ता किसी शब्दकोश में डुप्लिकेट कुंजी दर्ज करता है तो मैं एक त्रुटि उठाने का प्रयास करता हूं। शब्दकोश एक फ़ाइल में है और उपयोगकर्ता मैन्युअल रूप से फ़ाइल को संपादित कर सकता है।अगर

उदाहरण:

dico= {'root':{ 
       'a':{'some_key':'value',...}, 
       'b':{'some_key':'value',...}, 
       'c':{'some_key':'value',...}, 
       ... 

       'a':{'some_key':'value',...}, 
       } 
     } 

नई कुंजी 'a' पहले से ही मौजूद ...

मैं कैसे Dico का परीक्षण करने और उपयोगकर्ता को चेतावनी दी है जब मैं फ़ाइल से Dico लोड कर सकते हैं?

+0

आप फ़ाइल से शब्दकोश कैसे लोड कर रहे हैं? –

+1

@ ह्यूग बॉथवेल: 'एक्स आयात डीको' से – Thammas

उत्तर

12

dict के उप-वर्ग लिखें, __setitem__ को ओवरराइड करें जैसे कि मौजूदा कुंजी को बदलते समय यह त्रुटि उत्पन्न करता है; डिफॉल्ट ड्रामा बिल्ट-इन्स के बजाय अपने नए सबक्लास के कन्स्ट्रक्टर का उपयोग करने के लिए फ़ाइल को फिर से लिखें।

import collections 

class Dict(dict): 
    def __init__(self, inp=None): 
     if isinstance(inp,dict): 
      super(Dict,self).__init__(inp) 
     else: 
      super(Dict,self).__init__() 
      if isinstance(inp, (collections.Mapping, collections.Iterable)): 
       si = self.__setitem__ 
       for k,v in inp: 
        si(k,v) 

    def __setitem__(self, k, v): 
     try: 
      self.__getitem__(k) 
      raise ValueError("duplicate key '{0}' found".format(k)) 
     except KeyError: 
      super(Dict,self).__setitem__(k,v) 

फिर अपनी फ़ाइल

dico = Dict(
    ('root', Dict(
     ('a', Dict(
      ('some_key', 'value'), 
      ('another_key', 'another_value') 
     ), 
     ('b', Dict(
      ('some_key', 'value') 
     ), 
     ('c', Dict(
      ('some_key', 'value'), 
      ('another_key', 'another_value') 
     ), 

     .... 
    ) 
) 

फ़ाइल आयात के लिए dicts ({} अंकन का उपयोग लिखा के बजाय tuples का उपयोग कर के रूप में लिखा है, यह डिफ़ॉल्ट dict निर्माता का प्रयोग करेंगे, और डिक्टिव कन्स्ट्रक्टर उन्हें कभी भी प्राप्त करने से पहले डुप्लिकेट गायब हो जाएगा!)।

+0

यह सबसे अच्छा समाधान है! यह अपेक्षित अपवाद को तब तक बढ़ाता है जब आप वस्तुओं को एक-एक करके जोड़ने की कोशिश नहीं करते हैं, लेकिन जब आप ट्यूबल की सूची को दोहराए गए पहले आइटमों के साथ एक शब्दकोश में परिवर्तित करते हैं: डिक्ट ([(1, 2), (3, 4), (1, 6)])। – jciloa

1

पायथन का डिफ़ॉल्ट व्यवहार एक शब्दकोश घोषित करते समय चुपचाप डुप्लीकेट को ओवरराइट करना है।

आप अपनी खुद की शब्दकोश कक्षा बना सकते हैं जो जांच करेगा कि नया तत्व जोड़ने से पहले कोई आइटम पहले से ही एक शब्दकोश में था या नहीं। लेकिन फिर आपको उस फ़ाइल में dico की अपनी घोषणा को कुछ ऐसा करना होगा जो डुप्लीकेट की अनुमति देता है, उदाहरण के लिए टुपल्स की सूची की तरह।

फिर उस डेटा फ़ाइल को लोड करने पर, आप इसे अपने विशेष 'उप-वर्गीकृत' निर्देश में पार्स करेंगे।

4

आपको कस्टम निर्देश होना चाहिए जो कुंजी पहले से मौजूद होने पर ValueError के साथ अस्वीकार कर सकता है।

class RejectingDict(dict): 
    def __setitem__(self, k, v): 
     if k in self.keys(): 
      raise ValueError("Key is already present") 
     else: 
      return super(RejectingDict, self).__setitem__(k, v) 

यहां यह काम करता है।

>>> obj = RejectingDict() 
>>> obj[1] = True 
>>> obj[2] = False 
>>> obj 
{1: True, 2: False} 
>>> obj[1] = False 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "rejectingdict.py", line 4, in __setitem__ 
    raise ValueError("Key is already present") 
ValueError: Key is already present 
+1

ध्यान दें कि self.keys() में k (ओ) है, आपको शायद 'स्वयं में' का उपयोग करना चाहिए (चेक नहीं किया गया) – iggy

+0

यह अपेक्षित अपवाद नहीं बढ़ाता है जब आप बार-बार पहली वस्तुओं के साथ tuples की सूची को परिवर्तित करते हैं एक शब्दकोश में: अस्वीकार डिक्ट ([(1, 2), (3, 4), (1, 6)])। स्वीकार किए गए समाधान (ह्यूग बॉवेलवेल द्वारा) उस मामले के लिए भी काम करता है। – jciloa

+0

ओह, self.keys() का उपयोग करना बहुत धीमा है – spiritwolfform

3

गलत तरीके से
वापस जाने

from x import dico एक बहुत अच्छा विचार नहीं है - आप दे रहे हैं प्रयोक्ता संपादित करें कोड, जिसे फिर आप आँख बंद करके निष्पादित। आप import os; os.system("rm whatever"); dico = {} जैसे दुर्भावनापूर्ण सामान तक, सिंटैक्स त्रुटि के कारण सरल टाइपो का जोखिम चलाते हैं।

dict उपclassing के बारे में मतभेद मत करो। अपने स्वयं के dict-of-dicts लोडर लिखें। यह मुश्किल नहीं है ... डेटा फ़ाइल पढ़ें, प्रत्येक सम्मिलन से पहले जांचें कि कुंजी पहले से मौजूद है या नहीं; यदि ऐसा होता है, तो लाइन नंबर और डुप्लिकेट कुंजी और उसके मान जैसे सार्थक सामान के साथ एक त्रुटि संदेश लॉग करें। अंत में, अगर कोई त्रुटि हुई है, तो अपवाद उठाएं। आप पाते हैं कि ऐसा करने के लिए एक मौजूदा मॉड्यूल है ... पाइथन की आपूर्ति की गई कॉन्फ़िगरर्स उर्फ ​​कॉन्फ़िगरर्स आपको जो चाहिए वह प्रतीत नहीं होता है।

वैसे, शीर्ष स्तर पर एक 'रूट' कुंजी नहीं है बल्कि व्यर्थ है?

+0

आपकी टिप्पणी के लिए धन्यवाद। 'dico' वास्तव में एक सेटिंग्स फ़ाइल है। जैसा कि मैं एक अजगर शुरुआत कर रहा हूं और जैसा कि मैं उत्तर से सभी कोड नहीं समझता, मुझे लगता है कि मैं इसके बजाय ConfigParser का उपयोग करूंगा ... – Thammas

+0

@ थॉमस: हुह? (1) "" "डिको वास्तव में एक सेटिंग फाइल है" ":" आपके प्रश्न के अनुसार, 'dico'' x.py' नामक फ़ाइल में 3-स्तरीय स्रोत कोड डिक्शनरी [आपको आशा है !!] का नाम है (2) आपको यह इंप्रेशन देता है कि कॉन्फ़िगर पार्स सार्थक त्रुटि संदेशों के साथ डुप्लिकेट डिटेक्शन का समर्थन करता है? –

+0

आप सही हैं, dico file.py में शब्दकोश है ... मैंने गलत बात की थी ... आप ConfigParser के बारे में भी सही हैं! मैं जवाब में दिए गए कोड का अध्ययन करने की कोशिश करूंगा। – Thammas

1

आप यह सुनिश्चित करें कि एक त्रुटि डुप्लिकेट चाबी, बस का लाभ उठाने के अजगर की मूल कीवर्ड तर्क की जाँच के साथ dict निर्माण के दौरान उठाया है चाहते हैं:

> dict(a={}, a={}) 
SyntaxError: keyword argument repeated 

जब तक मैं कुछ याद कर रहा हूँ, वहाँ dict उपवर्ग करने की कोई जरूरत है ।

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