2010-03-11 14 views
31

मान लीजिए मेरे पास कोड है जो माता-पिता/बच्चों की संरचना को बनाए रखता है। ऐसी संरचना में मुझे परिपत्र संदर्भ मिलते हैं, जहां एक बच्चा माता-पिता को इंगित करता है और एक बच्चे को माता-पिता को इंगित करता है। क्या मुझे उनके बारे में चिंता करनी चाहिए? मैं पाइथन 2.5 का उपयोग कर रहा हूँ।क्या मुझे पायथन में परिपत्र संदर्भों के बारे में चिंता करनी चाहिए?

मुझे चिंतित है कि वे कचरा नहीं एकत्र होंगे और एप्लिकेशन अंततः सभी मेमोरी का उपभोग करेगा।

उत्तर

25

"चिंता" गलत है, लेकिन अगर आपके प्रोग्राम पता चला है धीमी गति से हो सकता है, अपेक्षा से अधिक स्मृति उपभोग करते हैं, या अजीब भरी है विराम, कारण वास्तव में उन कचरा संदर्भ लूपों में होने की संभावना है - उन्हें "सामान्य" (विश्वकोश) संदर्भ ग्राफ की तुलना में एक अलग प्रक्रिया द्वारा एकत्रित कचरा होने की आवश्यकता है, और यह संग्रह कभी-कभी होता है और यदि आपके पास बहुत कुछ हो तो धीमा हो सकता है ऐसे लूपों में बंधे ऑब्जेक्ट्स (चक्रीय-कचरा संग्रह भी अवरुद्ध होता है यदि लूप में किसी ऑब्जेक्ट में __del__ विशेष विधि है)।

तो, संदर्भ लूप आपके प्रोग्राम की शुद्धता को प्रभावित नहीं करेंगे, लेकिन इसके प्रदर्शन और/या पदचिह्न को प्रभावित कर सकते हैं।

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

हैं और जब आप चक्रीय कचरा संग्रहण के बारे में अधिक प्रत्यक्ष नियंत्रण लागू करने के लिए (या डिबगिंग करते हैं, देखते हैं कि क्या वास्तव में हो रहा है) चाहते हैं, पायथन के मानक पुस्तकालय में gc मॉड्यूल का उपयोग करें।

+0

प्लस 1। यदि आपके ऑब्जेक्ट विनाशकों के साइड इफेक्ट्स हैं, तो आप चक्रीय संदर्भों (और जब चीजें नष्ट हो जाती हैं) के बारे में कुछ और सावधानी से सोचना चाहेंगे। – speedplane

9

पायथन चक्र का पता लगाएगा और जब कोई बाहरी संदर्भ नहीं होगा तो स्मृति को छोड़ देगा।

+0

के पाठ्यक्रम मान लिया जाये कि कोई '__del__' तरीके हैं: हालांकि, बाद में मामले में समस्या यह है कि आप कमजोर संदर्भ नहीं दे सकता तरीकों है। जो सामान्य रूप से नहीं होना चाहिए, लेकिन आप कभी नहीं जानते। थोड़ी देर के लिए, यहां तक ​​कि 'संग्रह। ऑर्डर्ड डिक्ट' के कारण किसी कारण से था। – Antimony

15

प्रयोगात्मक: तुम ठीक हो:

import itertools 

for i in itertools.count(): 
    a = {} 
    b = {"a":a} 
    a["b"] = b 

यह लगातार रैम 3.6   MB का उपयोग कर में रहता है।

+2

कूल! तब मैं सुरक्षित हूँ। :) – bodacydo

+0

आपने किस कार्यान्वयन का उपयोग किया था? –

+0

@SargeBorsch CPython 2. कुछ। मुझे लगता है कि किसी भी बड़े कार्यान्वयन के समान व्यवहार करेंगे। – cobbal

5

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

+0

धन्यवाद कॉलिन। मुझे नहीं पता था कि वे "एक सामान्य चीज़" थे। वे मेरे लिए बहुत खास लग रहे थे। लेकिन अब मैंने अन्यथा सीखा। :) – bodacydo

+0

इसके अलावा, वे ग्राफ के लिए स्पष्ट रूप से आवश्यक हैं। – Antimony

3

मुझे नहीं लगता कि आपको चिंता करनी चाहिए। निम्नलिखित कार्यक्रम की कोशिश करो और आप देखेंगे कि यह सब स्मृति का उपभोग नहीं होगा:

while True: 
    a=range(100) 
    b=range(100) 
    a.append(b) 
    b.append(a) 
    a.append(a) 
    b.append(b) 
+0

इस टेस्ट कोड को लिखने के लिए धन्यवाद। मैंने इसके बारे में नहीं सोचा था। – bodacydo

+0

क्या आपका मतलब 'a.extend (बी)' नहीं है, 'संलग्न नहीं' है? – richizy

+4

@richizy मैं वास्तव में संलग्न करना चाहता हूं क्योंकि मैं ए और बी के संदर्भ में ए और बी के संदर्भ को सहेजना चाहता हूं, मानों पर नहीं। इस तरह परिपत्र संदर्भ होगा। '__del__' के बारे में नोट के लिए – douglaz

1

एक चर में सूचियों में विधियों के संदर्भों के साथ एक मुद्दा प्रतीत होता है। यहां दो उदाहरण दिए गए हैं। पहला व्यक्ति __del__ पर कॉल नहीं करता है। कमजोर के साथ दूसरा वाला __del__ के लिए ठीक है। http://docs.python.org/2/library/weakref.html

import sys, weakref 

class One(): 
    def __init__(self): 
     self.counters = [ self.count ] 
    def __del__(self): 
     print("__del__ called") 
    def count(self): 
     print(sys.getrefcount(self)) 


sys.getrefcount(One) 
one = One() 
sys.getrefcount(One) 
del one 
sys.getrefcount(One) 


class Two(): 
    def __init__(self): 
     self.counters = [ weakref.ref(self.count) ] 
    def __del__(self): 
     print("__del__ called") 
    def count(self): 
     print(sys.getrefcount(self)) 


sys.getrefcount(Two) 
two = Two() 
sys.getrefcount(Two) 
del two 
sys.getrefcount(Two) 
संबंधित मुद्दे

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