2011-06-02 12 views
5

मेरे पास एक ऐसी स्थिति है जिसमें मैं पहली वस्तु मौजूद होने तक एक ऑब्जेक्ट से दूसरे ऑब्जेक्ट में मैपिंग को बनाए रखना चाहता हूं। मेरा पहला विचार एक WeakKeyDictionary का उपयोग करना था।जीसी WeakKeyDories में परिपत्र संदर्भ हटा नहीं है?

import weakref 
import gc 

class M: 
    pass 

w = weakref.WeakKeyDictionary() 
m = M() 
w[m] = some_other_object 
del m 
gc.collect() 
print w.keys() 

यह ज्यादातर मामलों में ठीक काम करता है। हालांकि, उस मामले में जहां some_other_objectm है (या इसका संदर्भ है) M उदाहरण कचरा एकत्र नहीं किया जाएगा। (एक उदाहरण देखने के लिए, m साथ some_other_object की जगह)

बेशक

, अगर मैं वस्तु पर ही मानचित्रण संग्रहीत, यह कचरा एकत्र किया जाएगा जब मैं इसे नष्ट कर दिया:

import weakref 
import gc 

class M: 
    pass 

m = M() 
m.circular_reference = m 
r = weakref.ref(m) 
del m 
gc.collect() 
print r 

मैं परिणाम प्राप्त कर सकते हैं कमजोर मॉड्यूल का उपयोग करते हुए दूसरे उदाहरण का (यानी m को म्यूट किए बिना)?

दूसरे शब्दों में, क्या मैं किसी ऑब्जेक्ट को अपने आप को मैप करने के लिए कमजोर मॉड्यूल का उपयोग कर सकता हूं (या किसी अन्य ऑब्जेक्ट जिसमें इसका मजबूत संदर्भ है) और केवल ऑब्जेक्ट को याद रखें जब तक कि इसके अन्य संदर्भ न हों?

उत्तर

2

आपके पास इन उदाहरणों में वास्तव में परिपत्र संदर्भ नहीं हैं। अपने सर्कल प्रकार है:

WeakKeyDict -> मूल्य -> ​​कुंजी -> ...

तो dict मूल्य जिंदा है, जो बारी में महत्वपूर्ण जिंदा रहता है रहता है, और एक अलग तंत्र जो ऐसा नहीं करता के माध्यम से एक मजबूत संदर्भ शामिल है, कुंजी मूल्य को जीवित रखने के लिए निर्देश देता है। चूंकि यहां कोई उचित संदर्भ मंडल नहीं है, इसलिए जीसी किसी भी मुद्दे का पता नहीं लगाता है।(हालांकि, आपका दूसरा उदाहरण में एक परिपत्र संदर्भ होता है, यही कारण है कि यह पहले की तरह व्यवहार करता है)

मुझे संदेह है कि आपकी समस्या का एकमात्र समाधान यह सुनिश्चित करना है कि dict के मूल्यों में कभी भी मजबूत संदर्भ न हों (प्रत्यक्ष या अप्रत्यक्ष) dict में किसी भी कुंजी के लिए। यह srgerg प्रस्तावित के समान है, लेकिन सभी मूल्यों के कमजोर संदर्भ बनाने के बजाय, आप वाकई कमजोर होने के लिए कुंजी के संदर्भ चाहते हैं। उदाहरण के लिए:

import weakref 
import gc 

class M: 
    pass 

w = weakref.WeakKeyDictionary() 
key = M() 
val = M() 
val.keyRef = weakref.ref(val) 
w[key] = val 
print len(w) ## prints 1 
del key 
gc.collect() 
print len(w) ## prints 0 

इस तरह, वहाँ हमेशा मूल्यों को मजबूत संदर्भ हैं, लेकिन आप ध्यान से निर्धारित करने के लिए क्या dict से हटा दिया जाता चाबियाँ के लिए संदर्भ को नियंत्रित कर रहे हैं। आपके कार्यक्रम की जटिलता के आधार पर, यह लागू करने में समय लग सकता है, क्योंकि आपको चाबियों के सभी संदर्भ मैन्युअल रूप से ट्रैक करने की आवश्यकता है।

लेकिन शायद हम एक सरल समाधान प्रस्तावित कर सकता अगर आप हमें विशिष्ट समस्या के बारे में और अधिक बता ..

+0

क्या आप" एक अलग तंत्र के माध्यम से वाक्यांश को विस्तृत कर सकते हैं जिसमें मजबूत संदर्भ शामिल नहीं है "? यह तंत्र क्या है और आप क्यों कहते हैं कि यह एक मजबूत संदर्भ नहीं है? मैं सहमत हूं कि आपका निष्कर्ष (हालांकि असंतोषजनक है!), और मैं आपका जवाब स्वीकार करने के इच्छुक हूं, लेकिन मुझे इस बिंदु पर स्पष्टीकरण पसंद आएगा। – matthewwithanm

+0

इस नियम में मूल्य का एक मजबूत संदर्भ है। यदि कुंजी एकत्र की जाती है, तो ताना अधिसूचित किया जाता है और मूल्य के संदर्भ को जारी करता है। तो यह कुछ हद तक व्यवहार करता है जैसे कि कुंजी के मान का संदर्भ है (जो एक संदर्भ सर्कल पूरा करेगा), लेकिन वास्तविकता में कोई प्रत्यक्ष संदर्भ नहीं है। इसके बजाए, एक कुंजी के बिना समान परिणाम उत्पन्न करने के लिए कुंजी कुंजी और मूल्य के बीच बैठता है-> मान संदर्भ। क्या उससे मदद हुई? मुझे डर है कि मेरी व्याख्या थोड़ा सा परिपत्र है (और अब पन पूरा हो गया है कि पोस्ट संदर्भ खुद ही हैं)। – Luke

1

इस तरह के परिपत्र संदर्भों से निपटने में किसी के सिर की संभावना है, लेकिन, अवांछित, मैं वैसे भी आपके प्रश्न का उत्तर देने का प्रयास करूंगा।

एक अजगर शब्दकोश अपनी चाबियों और मानों दोनों के संदर्भों को संदर्भित करता है। WeakKeyDictionary स्टोर कमजोर इसकी चाबियों के संदर्भ, लेकिन मजबूत इसके मूल्यों के संदर्भ। तो आपके पहले उदाहरण में, यदि आप w[m] = m सेट करते हैं तो w में m का एक कमजोर संदर्भ है और m के लिए एक मूल्य के रूप में एक मजबूत संदर्भ है।

पायथन के कमजोर मॉड्यूल में एक वीकवेल्यू डिक्शनरी भी है जिसमें इसकी चाबियों के मजबूत संदर्भ और इसके मूल्यों के कमजोर संदर्भ हैं, लेकिन इससे आपकी समस्या हल नहीं होगी।

जो आप वास्तव में चाहते हैं वह एक शब्दकोश है जिसमें इसकी चाबियाँ और मूल्य दोनों के कमजोर संदर्भ हैं। निम्नलिखित कोड को स्पष्ट रूप से एक कमजोर संदर्भ शब्दकोश में प्रत्येक मान बनाता है:

import weakref 
import gc 

class M(): 
    pass 

class Other(): 
    pass 

m = M() 
w = weakref.WeakKeyDictionary() 
w[m] = weakref.ref(m) 
print len(w.keys()) # prints 1 
del m 
print len(w.keys()) # prints 0 

m = M() 
o = Other() 
o.strong_ref = m 
w[m] = weakref.ref(o) 
print len(w.keys()) # prints 1 
del m 
print len(w.keys()) # prints 1 
del o 
print len(w.keys()) # prints 0 

आप मूल्य एक कमजोर संदर्भ स्वचालित रूप से उप-classing WeakKeyDictionary से बना सकते हैं। नोट, हालांकि, यह नहीं वास्तविक WeakValueDictionary जैसा व्यवहार करता है क्योंकि इसमें कोई मान हटा दिए जाने पर शब्दकोश को सूचित करने के लिए कॉलबैक नहीं होता है।

class MyWeakKeyValueDictionary(weakref.WeakKeyDictionary): 
    def __init__(self): 
     weakref.WeakKeyDictionary.__init__(self) 

    def __setitem__(self, key, value): 
     weakref.WeakKeyDictionary.__setitem__(self, key, weakref.ref(value)) 

w2 = MyWeakKeyValueDictionary() 
m = M() 
w2[m] = m 
print len(w2.keys()) # prints 1 
del m 
print len(w2.keys()) # prints 0 

m = M() 
o = Other() 
o.strong_ref = m 
w2[m] = o 
print len(w2.keys()) # prints 1 
del m 
print len(w2.keys()) # prints 1 
del o 
print len(w2.keys()) # prints 0 

अंत में, हालांकि, मैं इस तरह वृत्तीय संदर्भ से निपटने के लिए और अधिक समस्याएं पैदा हो सकती की तुलना में यह लायक है की कोशिश कर रहा डर।

+0

बहादुर प्रयास के लिए धन्यवाद, लेकिन मैं नहीं है वास्तव में एक शब्दकोश है कि दोनों अपने कुंजी और करने के लिए कमजोर संदर्भ होते हैं चाहते हैं मान। यह देखने के लिए, उस मामले पर विचार करें जहां 'm'' m (m) 'के लिए मैप किया गया है। 'M' (' m.ref = (m) 'पर संदर्भ संग्रहीत करके इसे मैप करना वांछित के रूप में कार्य करता है: सूची तब तक स्मृति में रहेगी जब तक' m' करता है, लेकिन 'm' को हटाने से उसका कचरा संग्रह होगा । हालांकि, आपके द्वारा प्रस्तावित विधि के साथ, सूची में कभी भी (बाहरी) संदर्भ नहीं है। इसलिए, मूल्य तुरंत कचरा इकट्ठा किया जाएगा। – matthewwithanm

+0

डी ओह! मेरी आखिरी टिप्पणी में उदाहरण को 'm'' सेट (m) 'में मैप किया जाना चाहिए था। आप देखेंगे कि यदि आप 'w2 [m] = set (m) 'करते हैं, तो सेट तुरंत कचरा इकट्ठा किया जाएगा क्योंकि इसमें कोई मजबूत संदर्भ नहीं है। मुझे वास्तव में एक ** मजबूत ** मूल्य (जैसे संपत्ति की तरह) संदर्भित करना है, लेकिन किसी भी तरह कचरा कलेक्टर गोलाकार प्रकृति का एहसास करता है (जैसे यह 'm.circular_reference = set (m)') के लिए करता है। – matthewwithanm

+0

* 'सेट ([एम]) '(क्षमा करें। बहुत देर हो चुकी है।) – matthewwithanm

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