2009-03-24 8 views
16

में कमजोर सूची में मुझे कमजोर संदर्भों की एक सूची की आवश्यकता है जो मरने पर आइटम हटा देता है। वर्तमान में ऐसा करने का एकमात्र तरीका है सूची को फ़्लश करना (मैन्युअल रूप से मृत संदर्भों को हटा देना)।पायथन

मुझे पता है कि एक वीककेई डिक्शनरी और वीकवेल्यू डिक्शनरी है, लेकिन मैं वास्तव में वीकलिस्ट के बाद हूं, क्या ऐसा करने का कोई तरीका है?

यहाँ एक उदाहरण है:

import weakref 

class A(object): 
    def __init__(self): 
     pass 

class B(object): 
    def __init__(self): 
     self._references = [] 

    def addReference(self, obj): 
     self._references.append(weakref.ref(obj)) 

    def flush(self): 
     toRemove = [] 

     for ref in self._references: 
      if ref() is None: 
       toRemove.append(ref) 

     for item in toRemove: 
      self._references.remove(item) 

b = B() 

a1 = A() 
b.addReference(a1) 
a2 = A() 
b.addReference(a2) 

del a1 
b.flush() 
del a2 
b.flush() 
+0

आप को परिभाषित करें "मैन्युअल रूप से हटाने के" "संदर्भ" "मर", "फ्लश", हो सकता है? यह सवाल वास्तव में उन लोगों के बिना ज्यादा समझ में नहीं आता है। – hop

+0

मर = कमजोर संदर्भ अमान्य हो जाता है ("मृत")। संदर्भ = एक कमजोर संदर्भ (http://docs.python.org/library/weakref.html)। फ्लश = सूची में सभी संदर्भों पर मैन्युअल रूप से = पुनरावृत्ति को हटा दें जो अमान्य हैं उन्हें हटा दें। – Dan

+0

अभी तक बहुत स्पष्ट नहीं है, जब तक कि आप पहले से ही नहीं जानते कि – hop

उत्तर

5

तुम खुद आप कैसे किया है को लागू कर सकता है, ठीक उसी प्रकार है, लेकिन एक सूची उपवर्ग कि फ्लश कॉल (के साथ) एक आइटम का उपयोग करने के प्रयास करने से पहले।

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

यहां इस विधि का उपयोग करके लागू एक सूची वर्ग है। (ध्यान दें कि इसका परीक्षण नहीं किया गया है, और कुछ विधियों को बहुत कुशलता से कार्यान्वित नहीं किया गया है (उदाहरण के लिए, जो सिर्फ वास्तविक सूची में परिवर्तित होते हैं और उस पर विधि को कॉल करते हैं), लेकिन यह एक उचित प्रारंभिक बिंदु होना चाहिए:

import weakref 

class WeakList(list): 
    def __init__(self, seq=()): 
     list.__init__(self) 
     self._refs = [] 
     self._dirty=False 
     for x in seq: self.append(x) 

    def _mark_dirty(self, wref): 
     self._dirty = True 

    def flush(self): 
     self._refs = [x for x in self._refs if x() is not None] 
     self._dirty=False 

    def __getitem__(self, idx): 
     if self._dirty: self.flush() 
     return self._refs[idx]() 

    def __iter__(self): 
     for ref in self._refs: 
      obj = ref() 
      if obj is not None: yield obj 

    def __repr__(self): 
     return "WeakList(%r)" % list(self) 

    def __len__(self): 
     if self._dirty: self.flush() 
     return len(self._refs) 

    def __setitem__(self, idx, obj): 
     if isinstance(idx, slice): 
      self._refs[idx] = [weakref.ref(obj, self._mark_dirty) for x in obj] 
     else: 
      self._refs[idx] = weakref.ref(obj, self._mark_dirty) 

    def __delitem__(self, idx): 
     del self._refs[idx] 

    def append(self, obj): 
     self._refs.append(weakref.ref(obj, self._mark_dirty)) 

    def count(self, obj): 
     return list(self).count(obj) 

    def extend(self, items): 
     for x in items: self.append(x) 

    def index(self, obj): 
     return list(self).index(obj) 

    def insert(self, idx, obj): 
     self._refs.insert(idx, weakref.ref(obj, self._mark_dirty)) 

    def pop(self, idx): 
     if self._dirty: self.flush() 
     obj=self._refs[idx]() 
     del self._refs[idx] 
     return obj 

    def remove(self, obj): 
     if self._dirty: self.flush() # Ensure all valid. 
     for i, x in enumerate(self): 
      if x == obj: 
       del self[i] 

    def reverse(self): 
     self._refs.reverse() 

    def sort(self, cmp=None, key=None, reverse=False): 
     if self._dirty: self.flush() 
     if key is not None: 
      key = lambda x,key=key: key(x()) 
     else: 
      key = apply 
     self._refs.sort(cmp=cmp, key=key, reverse=reverse) 

    def __add__(self, other): 
     l = WeakList(self) 
     l.extend(other) 
     return l 

    def __iadd__(self, other): 
     self.extend(other) 
     return self 

    def __contains__(self, obj): 
     return obj in list(self) 

    def __mul__(self, n): 
     return WeakList(list(self)*n) 

    def __imul__(self, n): 
     self._refs *= n 
     return self 

[संपादित करें] एक और पूरी सूची कार्यान्वयन जोड़े

+0

जब यह पुनरावृत्ति के दौरान सूची आकार बदलता है तो यह कैसे व्यवहार करता है? मैं '__iter__' में लूप के बारे में बात कर रहा हूं और 'हटाएं' में। – Niriel

1

आप क्यों नहीं बस इस तरह यह नहीं कर सकते:।।

import weakref 

class WeakList(list): 
    def append(self, item): 
     list.append(self, weakref.ref(item, self.remove)) 

और फिर __iadd__ के लिए इसी तरह करते हैं, extend आदि मेरे लिए काम करता है

+1

उम्म ... यह काम नहीं करता है। मैंने पायथन 2.6 और 3.1 में चेक किया है और न ही दूसरे तर्क का समर्थन करता है: 'TypeError: append() वास्तव में एक तर्क लेता है (2 दिया गया) ' –

+0

जो सुपर (सूची, स्वयं) होगा .append आदि –

+0

@Mu माइंड: कोष्ठक जांचें! – user508402

5

आप वही कमजोर मॉड्यूल से वीकसेट का उपयोग कर सकते हैं (यह वास्तव में रास्ते में कहीं और परिभाषित किया गया है, लेकिन यह वहां आयात किया गया है)।

>>> from weakref import WeakSet 
>>> s = WeakSet() 
>>> class Obj(object): pass # can't weakref simple objects 
>>> a = Obj() 
>>> s.add(a) 
>>> print len(s) 
1 
>>> del a 
>>> print len(s) 
0 
+3

एक वीकसेट केवल हैशबल ऑब्जेक्ट्स स्टोर कर सकता है। –

+4

इसमें इसकी प्रविष्टियों के क्रम को संरक्षित करने की कमी भी नहीं है। – SingleNegationElimination

+2

@ पीटर ग्राहम और टोकन मैकगुय: ओपी ने ऑर्डर करने के लिए अपनी आवश्यकताओं को नहीं बताया। तो अगर वह सिर्फ कमजोर चीजों की एक [अनियंत्रित] बैग चाहता था, और यदि वे चीजें हैंशबल हैं, तो वीकसेट विचार व्यावहारिक दिखता है। यदि चीजें अपने स्वयं के डिज़ाइन की वस्तुएं हैं, तो शायद वह अपनी वस्तु में हैशबल आवश्यकता को पूरा कर सकता है। –

0

आप B का उपयोग करने की योजना कैसे बनाते हैं? केवल एक चीज मैं कभी weakref सूची मैं बनाया के साथ क्या है, इस पर पुनरावृति है, इसलिए इसके कार्यान्वयन सरल है:

import weakref 

class WeakRefList(object): 
    "weakref psuedo list" 
    def __init__(yo): 
     yo._items = list() 
    def __iter__(yo): 
     yo._items = [s for s in yo._items if s() is not None] 
     return (s() for s in yo._items if s() is not None) 
    def __len__(yo): 
     yo._items = [s for s in yo._items if s() is not None] 
     return len(yo._items) 
    def append(yo, new_item): 
     yo._items.append(weakref.ref(new_item)) 
     yo._items = [s for s in yo._items if s() is not None] 
2

कॉलबैक फ़ंक्शन एक weakref का दूसरा तर्क के लिए पारित का प्रयोग करें।

इस कोड को कार्य करना चाहिए:

import weakref 

class weakRefList(list): 

    def addReference(self, obj): 
     self._references.append(weakref.proxy(obj, self.remove)) 
5

जैसा कि मैंने आप की तरह एक weakref सूची की जरूरत है, मैं एक कर दिया है और pypi पर प्रकाशित।

अब

आप कर सकते हैं:

pip install weakreflist 

तो:

from weakreflist import WeakList