2010-08-05 6 views
7

यह पहली बार है जब मैं यहां लिखता हूं, क्षमा करें अगर संदेश अवांछित है या बहुत लंबा है।__getattr__ के लिए असममित व्यवहार, न्यूस्टाइल बनाम पुरानी कक्षाएं

मुझे आवश्यकता होने पर ऑब्जेक्ट्स सामग्री कैसे प्राप्त की जाती है, इस बारे में और अधिक समझने में दिलचस्पी थी। तो मैंने पाइथन 2.7 दस्तावेज "डेटा मॉडल" here शीर्षक से पढ़ा, मैंने __getattr__ से मुलाकात की और यह जांचने के लिए कि क्या मैं समझ गया हूं या नहीं, मैंने इन सरल (और अपूर्ण) स्ट्रिंग रैपर लिखे हैं।

class OldStr: 
    def __init__(self,val): 
    self.field=val 

    def __getattr__(self,name): 
    print "method __getattr__, attribute requested "+name 

class NewStr(object): 
    def __init__(self,val): 
    self.field=val 

    def __getattr__(self,name): 
    print "method __getattr__, attribute requested "+name 

जैसा कि आप देख सकते हैं कि वे पुराने स्टाइल बनाम न्यूस्टाइल कक्षाओं को छोड़कर समान हैं। चूंकि उद्धृत पाठ में कहा गया है कि __getattr__ "कॉल किया गया है जब एक विशेषता लुकअप को सामान्य स्थानों में विशेषता नहीं मिली है", मैं उन वर्गों के दो उदाहरणों पर एक ऑपरेशन करना चाहता था ताकि यह देखने के लिए कि क्या हुआ, एक समान व्यवहार की उम्मीद है।

लेकिन परिणाम मैं मुझे एक छोटा सा हैरान गया:

>>> x=OldStr("test") 
>>> x+x 
method __getattr__, attribute requested __coerce__ 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
TypeError: 'NoneType' object is not callable 

अच्छा है! मैंने __coerce__ के लिए एक विधि परिभाषित नहीं की है (हालांकि मुझे __add__ के लिए अनुरोध की उम्मीद थी, कभी नहीं :), इसलिए __getattr__ शामिल हो गया और एक बेकार चीज़ लौटा दी। लेकिन तब

>>> y=NewStr("test") 
>>> y+y 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for +: 'NewStr' and 'NewStr' 

क्यों ओल्डस्टएल वर्गों और Newstyle लोगों में __getattr__ के बीच इस विषम व्यवहार का उपयोग करते समय एक अंतर्निहित की तरह + ऑपरेटर? क्या कोई मुझे यह समझने में मदद कर सकता है कि क्या हो रहा है, और दस्तावेज पढ़ने में मेरी गलती क्या थी?

बहुत बहुत धन्यवाद, आपकी मदद की सराहना की जाती है!

+6

कृपया किसी भी चीज़ के लिए पुरानी शैली कक्षाओं का उपयोग न करें। वे स्पष्ट कारणों से बहिष्कृत हैं - इस तरह। चूंकि उन्हें बहिष्कृत किया गया है, यह जानकर कि वे कैसे काम करते थे, सहायक नहीं है। उन्हें छोड़ दें और आगे बढ़ें। –

+3

पुराने और नए वर्गों के व्यवहार की तुलना करने से यह पता चलता है कि नई शैली के वर्ग कैसे काम करते हैं, खासकर यदि आप पुरानी शैली के वर्गों से परिचित हैं। यह वास्तव में आश्चर्यजनक है कि वे विभिन्न तरीकों से काम करते हैं, और उम्मीद के अनुसार नए वर्गों के काम को जानना आरामदायक है। फिर भी, यह समझने की कोशिश करने में मूल्य है कि क्यों कोड का अर्थ यह है कि इससे कोई फर्क नहीं पड़ता कि संस्करण क्या है। –

उत्तर

2

आपके __getattr__ फ़ंक्शंस कुछ भी वापस नहीं कर रहे हैं। मुझे नहीं पता कि पुरानी शैली की कक्षा __add__ की तलाश करने से पहले __getattr__ क्यों कर रही है, लेकिन यह है, और यह None पर वापसी मूल्य को कॉल करने का प्रयास कर रहा है।

नई शैली की कक्षा सही कर रही है: आपने __add__ परिभाषित नहीं किया है, इसलिए यह नहीं जानता कि उन्हें कैसे जोड़ना है।

4

Special method lookup for new-style classes देखें।

क्लास ऑब्जेक्ट में विशेष तरीकों को सीधे देखा जाता है, उदाहरण ऑब्जेक्ट्स और इसके परिणामस्वरूप __getattr__() और __getattribute__() बाईपास किए जाते हैं। ठीक उसी कारण से, instance.__add__ = foobar काम नहीं करता है।

यह विशेषता पहुंच को तेज़ करने के लिए किया जाता है। विशेष तरीकों को अक्सर बार कहा जाता है, और उन्हें मानक के अधीन बनाते हैं, बल्कि जटिल विशेषता लुकअप दुभाषिया को काफी धीमा कर देगा।

पुरानी शैली के वर्गों के लिए विशेषता लुकअप बहुत कम जटिल है (सबसे विशेष रूप से पुरानी स्टाइल कक्षाएं वर्णनकर्ताओं का समर्थन नहीं करती हैं), इसलिए पुराने शैली वर्गों में विशेष तरीकों से अलग तरीके से इलाज करने का कोई कारण नहीं है।

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