2015-10-28 5 views
8

को कॉपी जब मैं वस्तु की एक गहरी प्रतिलिपि मैं यह त्रुटि आई बनाने की कोशिश मैं एक वर्ग है जो इसदीप कॉपी विफलता जब कस्टम वस्तु

class Dict2obj(dict): 
    __getattr__= dict.__getitem__ 

    def __init__(self, d): 
     self.update(**dict((k, self.parse(v)) 
          for k, v in d.iteritems())) 

    @classmethod 
    def parse(cls, v): 
    if isinstance(v, dict): 
     return cls(v) 
    elif isinstance(v, list): 
     return [cls.parse(i) for i in v] 
    else: 
     return v 

की तरह एक वस्तु के लिए एक शब्दकोश में परिवर्तित हो

import copy 
my_object = Dict2obj(json_data) 
copy_object = copy.deepcopy(my_object) 

File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 172, in deepcopy 
copier = getattr(x, "__deepcopy__", None) 
KeyError: '__deepcopy__' 

लेकिन मैं getatrDict2obj कक्षा में फ़ंक्शन ओवरराइड करता हूं, मैं गहरी प्रतिलिपि ऑपरेशन करने में सक्षम था। क्योंकि copy.deepcopy की कोशिश करता getattr(x, "__deepcopy__", None) कॉल करने के लिए नीचे दिए गए

class Dict2obj(dict): 

    __getattr__= dict.__getitem__ 

    def __init__(self, d): 
     self.update(**dict((k, self.parse(v)) 
          for k, v in d.iteritems())) 

    def __getattr__(self, key): 
     if key in self: 
      return self[key] 
     raise AttributeError 

    @classmethod 
    def parse(cls, v): 
     if isinstance(v, dict): 
      return cls(v) 
     elif isinstance(v, list): 
      return [cls.parse(i) for i in v] 
     else: 
      return v 

क्यों मैं आदेश वस्तुओं की एक deepcopy करने के लिए getattr विधि ओवरराइड करने के लिए की जरूरत है उदाहरण देखें इस वर्ग

उत्तर

6

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

getattr(object, name[, default])

वापसी वस्तु के नाम पर रखा गया विशेषता के मान -

यह the documentation for getattr() में दी गई है। नाम एक स्ट्रिंग होना चाहिए। यदि स्ट्रिंग ऑब्जेक्ट के गुणों में से एक का नाम है, तो परिणाम उस विशेषता का मान है। उदाहरण के लिए, Getattr (x, 'foobar') x.foobar के बराबर है। यदि नामांकित विशेषता मौजूद नहीं है, तो प्रदान किए जाने पर डिफ़ॉल्ट लौटा दिया जाता है, अन्यथा विशेषता Error उठाया जाता है।

इस रूप में है, अन्यथा यह AttributeError बबल सामने की सुविधा देता है काम करता है, अगर अंतर्निहित __getattr__AttributeError को जन्म देती है और default तर्क फोन AttributeErrorgetattr() समारोह द्वारा पकड़ा जाता है और यह डिफ़ॉल्ट तर्क देता है getattr() समारोह के लिए प्रदान किया गया। उदाहरण -

>>> class C: 
...  def __getattr__(self,k): 
...    raise AttributeError('asd') 
... 
>>> 
>>> c = C() 
>>> getattr(c,'a') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in __getattr__ 
AttributeError: asd 
>>> print(getattr(c,'a',None)) 
None 

लेकिन आपके मामले में, जब से तुम सीधे dict.__getitem__ आवंटित __getattr__ लिए, अगर नाम शब्दकोश में नहीं पाया जाता है, यह एक KeyError, न कि एक AttributeError को जन्म देती है और इसलिए यह getattr() और के द्वारा नियंत्रित नहीं प्राप्त करता है आपका copy.deepcopy() विफल रहता है।

आपको अपने getattr में KeyError को संभालना चाहिए और उसके बाद AttributeError बढ़ाएं। उदाहरण -

class Dict2obj(dict): 

    def __init__(self, d): 
     self.update(**dict((k, self.parse(v)) 
          for k, v in d.iteritems())) 

    def __getattr__(self, name): 
     try: 
      return self[name] 
     except KeyError: 
      raise AttributeError(name) 
    ... 
संबंधित मुद्दे