2011-09-22 16 views
6

मुझे इस बात की दिलचस्पी है कि प्रोग्रामर शायद रास्ते में फेंकने वाले बाधाओं के बावजूद पाइथन उदाहरण को __dict__ देखने के लिए एक तरीका है, क्योंकि इससे मुझे अनजान संदर्भ लूप और खुले संसाधनों जैसे समस्याओं को डीबग करने में मदद मिलेगी फ़ाइलें।क्या obj .__ dict__ का निरीक्षण किया जा सकता है यदि कक्षा में __dict__ चर है?

एक आसान उदाहरण है: यदि प्रोग्रामर keys() अपने स्वयं के वर्ग के पीछे छिपा हुआ है तो मैं dict सबक्लास की कुंजी कैसे देख सकता हूं? कि चारों ओर जिस तरह से मैन्युअल बजाय दे विरासत विधि के उपवर्ग के संस्करण फोन की dictkeys() विधि कॉल करने के लिए है:

# Simple example of getting to the real info 
# about an instance 

class KeyHidingDict(dict): 
    def keys(self): 
     return [] # there are no keys here! 

khd = KeyHidingDict(a=1, b=2, c=3) 
khd.keys()  # drat, returns [] 
dict.keys(khd) # aha! returns ['a', 'b', 'c'] 

अब मेरी वास्तविक सवाल है, मैं कैसे एक उदाहरण के __dict__ देख सकते हैं, कोई बात नहीं क्या प्रोग्रामर ने इसे मुझसे छिपाने के लिए किया होगा? अगर वे एक __dict__ वर्ग चर सेट तो यह उस वर्ग से विरासत में मिली किसी भी वस्तुओं की वास्तविक __dict__ शैडो लगता है:

# My actual question 

class DunderDictHider(object): 
    __dict__ = {'fake': 'dict'} 

ddh = DunderDictHider() 
ddh.a = 1 
ddh.b = 2 
print ddh.a  # prints out 1 
print ddh.__dict__ # drat, prints {'fake': 'dict'} 

के रूप में आप देख सकते हैं, वास्तविक विशेषता सेटिंग और हो रही के साथ हस्तक्षेप __dict__ के लिए यह झूठी मूल्य काम न करे, , लेकिन यह dir() को a और b छुपाकर fake को ऑब्जेक्ट के इंस्टेंस वैरिएबल के रूप में प्रदर्शित करके गुमराह करता है।

फिर, मेरा लक्ष्य एक ऐसा टूल लिखना है जो मुझे कक्षाओं के उदाहरणों को "वास्तव में क्या चल रहा है" देखने में मदद करता है जब मैं सोच रहा हूं कि कक्षा के उदाहरणों का एक सेट इतनी मेमोरी क्यों ले रहा है या इतनी सारी फाइलें खोल रहा है - और भले ही ऊपर की स्थिति बेहद संकलित हो, फिर भी इसके आस-पास एक रास्ता ढूंढने से उपकरण हमेशा काम करने की बजाय काम करेगा, "जब तक आप जिस कक्षा को देख रहे हैं, वह ... [असाधारण स्थिति का विवरण] है।"

मैंने सोचा था कि मैं बिना गलती किए की तरह कुछ के साथ __dict__ हड़पने के लिए सक्षम हो जाएगा:

dict_descr = object.__dict__['__dict__'] 
print dict_descr(ddh, DunderDictHider) 

लेकिन यह पता चला है कि object में __dict__ वर्णनकर्ता नहीं है। इसके बजाए, subtype_dict() सी फ़ंक्शन object के प्रत्येक सबक्लास से अलग से जुड़ा हुआ प्रतीत होता है जो प्रोग्रामर बनाता है; वर्णनकर्ता को नाम देने या लाने का कोई केंद्रीय तरीका नहीं है ताकि इसे उन वस्तुओं पर मैन्युअल रूप से लागू किया जा सके जिनकी कक्षा इसे छाया देती है।

कोई विचार, कोई भी? :)

+0

मुझे आगे सोचने में मदद करने के लिए धन्यवाद! तो यह एक तरीका है यदि विरासत पदानुक्रम 'वस्तु' → 'ए' →' बी' में, वस्तु 'बी' अपने उदाहरणों को '__dict__' विशेषताओं को छाया दे रही है। लेकिन क्या मैं सही हूं कि आपका विचार * सहायता * नहीं करता है यदि यह वर्ग 'ए' है जो एक भ्रामक '__dict__' वर्ग विशेषता को परिभाषित कर रहा है? –

उत्तर

0

यह एक इस विषय में Jerub जवाब पर आधारित है: What is a metaclass in Python?

आप प्राप्त कर सकते हैं आप metaclasses साथ क्या खोज रहे हैं।

सबसे पहले आप एक metaclass बनाने की जरूरत:

def test_metaclass(name, bases, dict): 
    print 'The Class Name is', name 
    print 'The Class Bases are', bases 
    print 'The dict has', len(dict), 'elems, the keys are', dict.keys() 

    return dict 

निश्चित रूप से प्रिंट necessery नहीं हैं।

class DunderDictHider(object): 
    __metaclass__ = test_metaclass 
    __dict__ = {'fake': 'dict'} 

अब आप द्वारा repr(DunderDictHider)

निर्गम (print repr(DunderDictHider) लाइन के साथ) सभी प्रारंभ elems की पहुंच है:

The Class Name is DunderDictHider 
The Class Bases are (<type 'object'>,) 
The dict has 3 elems, the keys are ['__dict__', '__module__', '__metaclass__'] 
{'__dict__': {'fake': 'dict'}, '__module__': '__main__', '__metaclass__': <function test_metaclass at 0x1001df758>} 

हर बार

तो फिर मुझे अपने नए DunderDictHider परिचय देना आप

if '__dict__' in repr(DunderDictHider) 
आज़मा सकते हैं

यह जानने के लिए कि क्या यह कक्षा __dict__ को छिपाने की कोशिश करती है या नहीं। याद रखें, कि repr आउटपुट एक स्ट्रिंग है। यह बेहतर किया जा सकता है, लेकिन यह विचार खुद ही है।

+0

मैं कहता हूं कि यह एक समारोह है अगर इसे मेटाक्लास को कॉल करना उचित नहीं है। निश्चित रूप से, यह मान्य है, लेकिन यह * वर्ग * नहीं है। –

+0

मैं थोड़ा उलझन में हो सकता है - मेरे सवाल (क) वस्तु उदाहरणों कि (ख) कि अन्य प्रोग्रामर लिखा है मनमाने ढंग से कक्षाओं से विरासत और मैं बचा तकनीक है कि आत्मनिरीक्षण मुश्किल हो जाएगा करने के लिए भरोसा नहीं कर सकते कि राज्य की जांच के बारे में था। लेकिन: (ए) मुझे आपके उत्तर में कोई ऑब्जेक्ट उदाहरण नहीं दिखाई देता है। (बी) यदि मैं उन कक्षाओं को नियंत्रित नहीं करता जो प्रोग्रामर लिख रहे हैं, तो मैं मेटाक्लास को कैसे नियंत्रित कर रहा हूं? –

1

मुझे यकीन है कि मैं के साथ खुश हूँ नहीं कर रहा हूँ कि यह कैसे सरल है:

>>> class DunderDictHider(object): 
...  __dict__ = {'fake': 'dict'} 
... 
>>> ddh = DunderDictHider() 
>>> ddh.a = 1 
>>> ddh.b = 2 
>>> 
>>> print ddh.a 
1 
>>> print ddh.__dict__ 
{'fake': 'dict'} 

समस्या यह है कि वर्ग को धोखा दे रहा है? उसे फिक्स करें!

>>> class DictUnhider(object): 
...  pass 
... 
>>> ddh.__class__ = DictUnhider 
>>> print ddh.a 
1 
>>> print ddh.__dict__ 
{'a': 1, 'b': 2} 

और वहां यह है। यद्यपि कक्षा किसी भी स्लॉट को परिभाषित करती है, हालांकि यह पूरी तरह विफल हो जाती है।

>>> class DoesntHaveDict(object): 
...  __slots__ = ['a', 'b'] 
... 
>>> dhd = DoesntHaveDict() 
>>> dhd.a = 1 
>>> dhd.b = 2 
>>> 
>>> print dhd.a 
1 
>>> dhd.__class__ = DictUnhider 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: __class__ assignment: 'DoesntHaveDict' object layout differs from 'DictUnhider' 
>>> 
+0

'__slots__' अभी भी' __dict__' को परिभाषित कर सकता है जो समान नाम के सामान्य, डिफ़ॉल्ट स्लॉट के रूप में काम करेगा। क्लास में वास्तविक स्लॉट सेटअप नहीं होने पर भी, आप '__slots__' var मास्क कर सकते हैं। यहां तक ​​कि अन्य धागे की अनुपस्थिति कि एक ही समय में वस्तु का उपयोग कर किया जा सकता है के रूप में मैं यह परीक्षण कर रहा हूँ में - – SingleNegationElimination

+0

के बाद से पूरे मुद्दे * उन्हें बदले बिना वस्तुओं आत्मनिरीक्षण करने के लिए * था, मैं पहले से ही वर्ग के लिए समायोजन करने के विचार खारिज कर दिया था , इस समाधान के लिए मुझे ऑब्जेक्ट्स के पूरे समूहों के '__class__' को स्विच करना होगा, जबकि मैं उन्हें संसाधनों और खुली फ़ाइलों के लिए कर सकता हूं। लेकिन मैं इस बारे में और सोचूंगा कि मुझे वास्तव में इस संभावना को अनदेखा करना चाहिए या नहीं। हम्म। –