2011-06-20 10 views
6

में डिफ़ॉल्ट मान वापस करने का प्रयास करते समय पाइथन अचार दुर्घटना मेरे पास कक्षा की तरह एक शब्दकोश है जिसका उपयोग मैं कुछ मानों को गुणों के रूप में संग्रहीत करने के लिए करता हूं। मैंने हाल ही में कुछ तर्क (__getattr__) को वापस करने के लिए जोड़ा है यदि कोई विशेषता मौजूद नहीं है। जैसे ही मैंने यह अचार दुर्घटनाग्रस्त कर दिया, और मैं कुछ अंतर्दृष्टि क्यों चाहता था?__getattr__

टेस्ट कोड:

import cPickle 
class DictionaryLike(object): 
    def __init__(self, **kwargs): 
     self.__dict__.update(kwargs) 

    def __iter__(self): 
     return iter(self.__dict__) 

    def __getitem__(self, key): 
     if(self.__dict__.has_key(key)): 
      return self.__dict__[key] 
     else: 
      return None 

    ''' This is the culprit...'''  
    def __getattr__(self, key): 
     print 'Retreiving Value ' , key 
     return self.__getitem__(key) 

class SomeClass(object): 
    def __init__(self, kwargs={}): 
     self.args = DictionaryLike(**kwargs) 


someClass = SomeClass() 
content = cPickle.dumps(someClass,-1) 
print content 

परिणाम:

Retreiving Value __getnewargs__ 
Traceback (most recent call last): 
    File <<file>> line 29, in <module> 
    content = cPickle.dumps(someClass,-1) 
TypeError: 'NoneType' object is not callable` 

मैं कुछ बेवकूफ क्या किया? मैंने एक पोस्ट पढ़ा था कि अगर कोई कुंजी मौजूद नहीं है तो मुझे एक अपवाद फेंकने की आवश्यकता हो सकती है? अगर ऐसा कोई मामला है तो अपवाद फेंकने के बिना मैं जो हासिल करना चाहता हूं उसे हासिल करने का कोई आसान तरीका है?

अंत परिणाम यह हुआ कि कुछ कॉल

someClass.args.i_dont_exist 

मैं चाहता हूँ अगर यह कोई नहीं लौटने के लिए है।

def __getattr__(self, key): 
    i = self.__getitem__(key) 
    if i == None: 
     raise AttributeError 
    return self.__getitem__(key) 

मुझे लगता है कि इस व्यवहार के लिए आवश्यक है जा रहा हूँ:

उत्तर

13

कार्यान्वयन __getattr__ थोड़ा मुश्किल है, क्योंकि इसे प्रत्येक गैर-मौजूदा विशेषता के लिए बुलाया जाता है। आपके मामले में, pickle मॉड्यूल __getnewargs__ विशेष विधि के लिए आपकी कक्षा का परीक्षण करता है और None प्राप्त करता है, जो स्पष्ट रूप से कॉल करने योग्य नहीं है।

आप __getattr__ को बदलने के लिए जादू नाम के लिए आधार कार्यान्वयन कॉल करने के लिए चाहते हो सकता है:

def __getattr__(self, key): 
    if key.startswith('__') and key.endswith('__'): 
     return super(DictionaryLike, self).__getattr__(key) 
    return self.__getitem__(key) 

मैं आमतौर पर, एक अंडरस्कोर के साथ शुरू सभी के नाम के माध्यम से पारित ताकि मैं आंतरिक प्रतीकों के लिए जादू से बचने कर सकते हैं।

+0

मुझे लगता है कि यह मेरे मामले के लिए सबसे अच्छा हो सकता है, क्योंकि _ और \ _ \ _ कभी भी विशेषता नाम नहीं होंगे। – Nix

+0

यह वास्तव में चालाक है मैंने कभी ऐसा नहीं सोचा – GWW

+0

दोस्त आपने मुझे इतना बचाया – Greg

5

आप एक AttributeError को बढ़ाने के लिए एक विशेषता अपनी कक्षा में मौजूद नहीं है जब की जरूरत है। getattr के लिए अजगर दस्तावेज से, "जब एक विशेषता लुकअप को सामान्य स्थानों में विशेषता नहीं मिली है (यानी यह एक उदाहरण विशेषता नहीं है और न ही यह स्वयं के लिए वर्ग के पेड़ में पाया जाता है)। नाम विशेषता नाम है। यह विधि (गणना) विशेषता मान वापस करना चाहिए या एक विशेषता त्रुटि अपवाद उठाएं। "

अचार को बताने का कोई तरीका नहीं है कि जिस विशेषता को वह खोज रहा है वह तब तक नहीं मिला जब तक आप अपवाद नहीं उठाते। उदाहरण के लिए, आपके त्रुटि संदेश में अचार __getnewargs__ नामक एक विशेष कॉल करने योग्य विधि की तलाश में है, अचार की अपेक्षा है कि यदि विशेषता त्रुटि अपवाद नहीं मिलता है तो वापसी मान कॉल करने योग्य है।

मुझे लगता है कि आप के आसपास एक संभावित काम शायद सभी विशेष तरीकों को परिभाषित करने का प्रयास कर सकता है अचार डमी विधियों के रूप में देख रहा है?

+0

क्या इस के आसपास जाने का कोई तरीका है (क्या आपने मेरा अंतिम संपादन देखा था)? – Nix

+0

@Nix: ओह, मैंने आपकी आखिरी टिप्पणी नहीं देखी – GWW

+0

जो भी मैं चाहता हूं उसे प्राप्त करना संभव नहीं है ... मैं बस हर बार हैशर की जांच करना चाहता था। – Nix

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