5

का उपयोग कर एक weakref उपयोग करने के लिए एक डेकोरेटर नहीं संशोधित कोशिश कर के बिना __get__ के माध्यम से __iadd__ लागू, मैं निम्नलिखित व्यवहार भर में ठोकर खाई उम्मीद है कि दोनों मामले समान व्यवहार करेंगे। इसके अलावा, संदर्भ गिनती और ऑब्जेक्ट आजीवन की मेरी समझ से, मुझे विश्वास था कि दोनों मामलों में वस्तु मुक्त होनी चाहिए।मेमोरी रिसाव जब अस्थायी

मैं दोनों python2.7 और python3.3 पर यह परीक्षण किया है।

यह एक बग या जानबूझकर व्यवहार है? क्या दोनों कॉल अपेक्षित परिणाम प्राप्त करने का कोई तरीका है (वस्तु को प्रश्न में मुक्त करें)?

मैं proxy में एक weakref उपयोग करने के लिए, क्योंकि इस बाध्य तरीकों के लिए सही वस्तु जीवन अर्थ विज्ञान नष्ट कर देता है नहीं करना चाहती:

a = A() 
descr = a.descr 
del a # a is kept alive since descr is a bound method to a 
descr() # should execute a.descr() as expected 

उत्तर

5

दो codepaths बराबर नहीं हैं।

इन-प्लेस दो ऑपरेटरों, असाइनमेंट लक्ष्य और आइटम जोड़े गए कार्यों को जोड़ता है। test1 में temp, एक स्थानीय चर, और इन-जगह इसके अलावा करने के लिए अनुवाद किया है है निम्नलिखित:

temp = temp.__iadd__(object()) 

और जब से तुम self लौट सकते हैं और temp, एक ही वस्तु को संदर्भित करता है इस temp = temp हो जाता है और उस संदर्भ को साफ किया जाता है समारोह समाप्त होने के बाद।

test2 में, आप जटिल मामलों, के बाद से अब वर्णनकर्ता फिर से शामिल हो रही कर रहे हैं:

a.descr += object() 

हो जाता है:

a.descr = A.__dict__['descr'].__get__(a, A).__iadd__(object()) 

ताकि आप विशेषता a.descr उदाहरण के लिए A.__dict__['descr'].__get__(a, A) का परिणाम असाइन करना; वर्णनकर्ता के पास __set__() विधि नहीं है और परामर्श नहीं किया जाता है।

लेकिन, और यहाँ पकड़ है, proxy वस्तु ही a के लिए एक संदर्भ रखती है, a.descr.instancea लिए एक संदर्भ है! आप एक परिपत्र संदर्भ बनाया।

यह संदर्भ ऑब्जेक्ट को कमजोर संदर्भ के माध्यम से दिखाने के लिए काफी समय तक जीवित रहता है, लेकिन जैसे ही कचरा संग्रहण प्रक्रिया इस चक्र को चलाती है और टूट जाती है, a वैसे भी चली जाएगी।

इस कहानी का नैतिक? गैर-डेटा वर्णनकर्ता के साथ संयोजन में __iadd__ का उपयोग न करें; शामिल दोनों __get__और__set__ क्योंकि आप जब परिणाम वापस असाइन किया गया है कि क्या होता है नियंत्रित करने के लिए की जरूरत है।

+0

दरअसल, जोड़ने 'gc.collect()' 'is_leaky' वृत्तीय संदर्भ टूट जाता है और कारण बनता है' is_leaky (test2) 'झूठी वापस जाने के लिए करने के लिए। – unutbu

+0

हां, a.descr .__ iadd __ (ऑब्जेक्ट()) के लिए test2 को बदलने के परिणामस्वरूप दूसरी झूठी होती है। – BartoszKP

+1

वाह। यह सूक्ष्म है। डिस्क्रिप्टर को एनओपी '__set__' जोड़ना समस्या को हल करता है। आपका बहुत बहुत धन्यवाद! – coldfix

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