2011-02-02 12 views
55
>>> class A(object): pass 
... 
>>> A.__dict__ 
<dictproxy object at 0x173ef30> 
>>> A.__dict__.__dict__ 
Traceback (most recent call last): 
    File "<string>", line 1, in <fragment> 
AttributeError: 'dictproxy' object has no attribute '__dict__' 
>>> A.__dict__.copy() 
{'__dict__': <attribute '__dict__' of 'A' objects> ... } 
>>> A.__dict__['__dict__'] 
<attribute '__dict__' of 'A' objects> # What is this object? 

यदि मैं A.something = 10 करता हूं, तो यह A.__dict__ में जाता है। A.__dict__.__dict__ में पाया गया, और इसमें कुछ कब होता है?एक पायथन कक्षा के __dict __.__ dict__ विशेषता क्या है?

+6

एक अधिक उपयुक्त उदाहरण चर 'ive' होगा। कम से कम यह इसे 'ए .__ dict __ [' ive ']' प्रश्न बना देगा;) मैं खुद को – Joakim

उत्तर

77

सभी A.__dict__.__dict__ पहले A.__dict__['__dict__'] से अलग है, और पूर्व मौजूद नहीं है। उत्तरार्द्ध __dict__ विशेषता है कि कक्षा के उदाहरण होंगे। यह एक वर्णनात्मक वस्तु है जो विशिष्ट उदाहरण के लिए विशेषताओं के आंतरिक शब्दकोश को लौटाती है। संक्षेप में, __dict__ किसी ऑब्जेक्ट की विशेषता ऑब्जेक्ट के __dict__ में संग्रहीत नहीं की जा सकती है, इसलिए इसे कक्षा में परिभाषित वर्णक के माध्यम से एक्सेस किया जाता है।

इसे समझने के लिए, आपको documentation of the descriptor protocol पढ़ना होगा।

लघु संस्करण:

  1. वर्ग A, instance.__dict__ के लिए उपयोग A.__dict__['__dict__'] द्वारा प्रदान की जाती है की एक उदाहरण के लिए जो vars(A)['__dict__'] के समान है।
  2. कक्षा ए के लिए, A.__dict__ तक पहुंच type.__dict__['__dict__'] (सिद्धांत में) द्वारा प्रदान की जाती है जो vars(type)['__dict__'] के समान है।

लंबे संस्करण:

दोनों वर्गों और वस्तुओं, दोनों विशेषता ऑपरेटर (वर्ग या metaclass के __getattribute__ के माध्यम से कार्यान्वित) के माध्यम से गुण के लिए पहुँच प्रदान और __dict__ विशेषता/प्रोटोकॉल है जिसके द्वारा प्रयोग किया जाता है vars(ob)

सामान्य वस्तुओं के लिए, __dict__ वस्तु एक अलग dict वस्तु है, जो गुण संग्रहीत करता है बनाता है, और __getattribute__ पहले की कोशिश करता इसे उपयोग और (वर्णनकर्ता का उपयोग करके कक्षा में विशेषता के लिए देखने के लिए प्रयास करने से पहले वहाँ से गुण प्राप्त करने के लिए प्रोटोकॉल, और __getattr__ पर कॉल करने से पहले)। कक्षा पर __dict__ वर्णनकर्ता इस शब्दकोश तक पहुंच लागू करता है।

  • x.name क्रम में उन की कोशिश कर के बराबर है: x.__dict__['name'], type(x).name.__get__(x, type(x)), type(x).name
  • x.__dict__ ही करता है लेकिन स्पष्ट कारणों

यह instance की __dict__ करने के लिए असंभव है के रूप में के लिए पहले छोड़ देता है उदाहरण के __dict__ में संग्रहीत किया जाए, इसे सीधे वर्णक प्रोटोकॉल के माध्यम से एक्सेस किया जाता है, और उदाहरण में एक विशेष क्षेत्र में संग्रहीत किया जाता है।

कक्षाओं के लिए एक समान परिदृश्य सत्य है, हालांकि उनके __dict__ एक विशेष प्रॉक्सी ऑब्जेक्ट है जो एक शब्दकोश होने का नाटक करता है (लेकिन आंतरिक रूप से नहीं हो सकता है), और आपको इसे बदलने या इसे किसी अन्य के साथ बदलने की अनुमति नहीं देता है। यह प्रॉक्सी आपको अन्य वर्गों के बीच विशिष्ट वर्गों के गुणों तक पहुंचने की अनुमति देता है, और इसके आधारों में से किसी एक में परिभाषित नहीं किया जाता है। उदाहरणों, __weakref__ जो weakref द्वारा आंतरिक रूप से प्रयोग किया जाता है की विशेषताओं के भंडारण के लिए __dict__, और वर्ग के docstring -

डिफ़ॉल्ट रूप से, एक खाली वर्ग के एक vars(cls) तीन वर्णनकर्ता किया जाता है। यदि आप __slots__ को परिभाषित करते हैं तो पहले दो चले जा सकते हैं। तब आपके पास __dict__ और __weakref__ विशेषताएँ नहीं होंगी, लेकिन इसके बजाय आपके पास प्रत्येक स्लॉट के लिए एक एकल श्रेणी विशेषता होगी। उदाहरण के गुण तब एक शब्दकोश में संग्रहीत नहीं किए जाएंगे, और उन्हें एक्सेस कक्षा के संबंधित वर्णनकर्ताओं द्वारा प्रदान किया जाएगा।


और अंत में, असंगति कि A.__dict__A.__dict__['__dict__'] से अलग है क्योंकि विशेषता __dict__ अपवाद द्वारा, है, कभी नहींvars(A) में देखा, तो क्या यह के लिए सच है व्यावहारिक रूप से किसी अन्य के लिए सच नहीं है विशेषता जो आप उपयोग करेंगे। उदाहरण के लिए, A.__weakref__A.__dict__['__weakref__'] जैसा ही है। यदि यह असंगतता मौजूद नहीं है, तो A.__dict__ का उपयोग नहीं करेगा, और आपको हमेशा vars(A) का उपयोग करना होगा।

+5

विस्तृत उत्तर के लिए धन्यवाद। हालांकि मुझे इसे कुछ बार पढ़ना पड़ा, मुझे लगता है कि यह कुछ समय हो गया है क्योंकि मैंने पाइथन के इतने सारे नए विवरण सीखे हैं। – porgarmingduod

7

A.__dict__A विशेषताओं को संग्रहीत करने वाला एक शब्दकोश है, A.__dict__['__dict__'] उसी A.__dict__ विशेषता का प्रत्यक्ष संदर्भ है।

A.__dict__ में स्वयं (एक प्रकार का) संदर्भ शामिल है। "दयालु" भाग यह है कि अभिव्यक्ति A.__dict__ सामान्य dict के बजाय dictproxy देता है।

>>> class B(object): 
...  "Documentation of B class" 
...  pass 
... 
>>> B.__doc__ 
'Documentation of B class' 
>>> B.__dict__ 
<dictproxy object at 0x00B83590> 
>>> B.__dict__['__doc__'] 
'Documentation of B class' 
+5

'ए .__ dict __ [' __ dict __ '] 'ए .__ dict__ का संदर्भ नहीं दूंगा '। यह उदाहरणों की '__dict__' विशेषता लागू करता है। अपने लिए यह कोशिश करने के लिए, 'ए .__ dict __ [' __ dict __ '] .__ प्राप्त करें __ (ए(), ए) 'ए()' के गुण देता है, जबकि 'ए .__ dict __ [' __ dict __ '] .__ __ (ए, प्रकार) 'विफल रहता है। –

5

कुछ अन्वेषण करने दें!

>>> A.__dict__['__dict__'] 
<attribute '__dict__' of 'A' objects> 

मुझे आश्चर्य है कि यह क्या है?

>>> type(A.__dict__['__dict__']) 
<type 'getset_descriptor'> 

getset_descriptor ऑब्जेक्ट में कौन से गुण हैं?

>>> type(A.__dict__["__dict__"]).__dict__ 
<dictproxy object at 0xb7efc4ac> 

कि dictproxy की एक प्रति करके हम कुछ रोचक गुण, विशेष रूप से __objclass__ और __name__ पा सकते हैं।

>>> A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__ 
(<class '__main__.A'>, '__dict__') 

तो __objclass__A और __name__ के लिए एक संदर्भ सिर्फ स्ट्रिंग '__dict__', एक विशेषता शायद का नाम है?

>>> getattr(A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__) == A.__dict__ 
True 

हमारे पास यह है! A.__dict__['__dict__'] एक ऑब्जेक्ट है जो A.__dict__ पर वापस जा सकता है।

+0

पीईपी 252 कहता है कि '__objclass__' वह वर्ग है जो इस विशेषता को _defined_ है, न कि उस वर्ग की विशेषता है। यह आपके 'getattr' उदाहरण को गलत बनाता है। एक और सही एक 'getattr (ए() .__ dict __ [' __ dict __ '] होगा .__ objclass__, ए .__ dict __ [' __ dict __ '] .__ नाम __) ' –

4

आप इस के अधिक समझने के लिए निम्नलिखित सरल उदाहरण की कोशिश कर सकते हैं:

>>> class A(object): pass 
... 
>>> a = A() 
>>> type(A) 
<type 'type'> 
>>> type(a) 
<class '__main__.A'> 
>>> type(a.__dict__) 
<type 'dict'> 
>>> type(A.__dict__) 
<type 'dictproxy'> 
>>> type(type.__dict__) 
<type 'dictproxy'> 
>>> type(A.__dict__['__dict__']) 
<type 'getset_descriptor'> 
>>> type(type.__dict__['__dict__']) 
<type 'getset_descriptor'> 
>>> a.__dict__ == A.__dict__['__dict__'].__get__(a) 
True 
>>> A.__dict__ == type.__dict__['__dict__'].__get__(A) 
True 
>>> a.__dict__ == type.__dict__['__dict__'].__get__(A)['__dict__'].__get__(a) 
True 

ऊपर के उदाहरण से, ऐसा लगता है कि वर्ग वस्तुओं गुण अपनी कक्षा से जमा हो जाती है, वर्ग के गुणों उनकी श्रेणी के आधार पर जमा हो जाती है जो metaclasses हैं। यह भी सत्यापित है:

>>> a.__dict__ == A.__getattribute__(a, '__dict__') 
True 
>>> A.__dict__ == type.__getattribute__(A, '__dict__') 
True 
संबंधित मुद्दे