associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

WeakList

Receita: Weak List

O módulo weakref contém duas implementações de weakdicts, dicionários que não aumentam a contagem de referências dos objetos: um que usa weakrefs para valores e o outro para chaves. Essa receita traz a implementação de uma weaklist, que você pode usar em situações que precise armazenar objetos sem aumentar sua contagem de referências. Caches de objetos e listas de clientes de um servidor são um bom exemplo.

Código

   1 import weakref
   2 
   3 
   4 class WeakList(list):
   5 
   6     def __add__(self, y):
   7         l = [i() for i in self]
   8         return list.__add__(l, y)
   9 
  10     def __contains__(self, y):
  11         ref = weakref.ref(y)
  12         return list.__contains__(self, ref)
  13 
  14     def __eq__(self, y):
  15         l = [i() for i in self]
  16         return list.__eq__(l, y)
  17 
  18     def __repr__(self):
  19         return "<WeakList at %s>" % id(self)
  20 
  21     def __getitem__(self, i):
  22         ref = list.__getitem__(self, i)
  23         return ref()
  24 
  25     def __setitem__(self, i, y):
  26         ref = weakref.ref(y)
  27         list.__setitem__(self, i, ref)
  28     
  29     def append(self, y):
  30         list.append(self, weakref.ref(y))
  31 
  32     def count(self, y):
  33         l = [x() for x in self]
  34         return list.count(l, y)
  35 
  36     def extend(self, y):
  37         for o in y:
  38             list.append(self, weakref.ref(o))
  39 
  40     def index(self, y):
  41         ref = weakref.ref(y)
  42         return list.index(self, ref)
  43 
  44     def insert(self, i, y):
  45         ref = weakref.ref(y)
  46         list.insert(self, i, ref)        
  47 
  48     def pop(self):
  49         ref = list.pop(self)
  50         return ref()
  51 
  52     def remove(self, y):
  53         ref = weakref.ref(y)
  54         list.remove(self, ref)
  55 
  56     def sort(self, cmpfunc=None):
  57 
  58         if cmpfunc is None:
  59             def n_cmpfunc(x, y):
  60                 if x() >  y(): return 1
  61                 if x() == y(): return 0
  62                 if x() <  y(): return -1
  63             
  64         else:
  65             def n_cmpfunc(x, y):
  66                 return cmpfunc(x(), y())
  67 
  68         list.sort(self, n_cmpfunc)    

Teste

   1 import unittest
   2 import weaklist
   3 import weakref
   4 import random
   5 
   6 
   7 class Object(object):
   8     pass
   9 
  10 class TestWeakList(unittest.TestCase):
  11     def setUp(self):
  12         self.list = weaklist.WeakList()
  13 
  14     def tearDown(self):
  15         del self.list
  16 
  17     def testAttributes(self):
  18         for attr in dir(list):
  19             self.assert_(attr in dir(self.list))
  20 
  21     def testSetItem(self):
  22         o = Object()
  23         list.append(self.list, None)
  24         self.list[0] = o
  25         self.assert_(list.__getitem__(self.list, 0)() is o)
  26 
  27     def testGetItem(self):
  28         o = Object()
  29         list.append(self.list, weakref.ref(o))
  30         self.assert_(self.list[0] is o)
  31 
  32     def testDelItem(self):
  33         o = Object()
  34         ref = weakref.ref(o)
  35         list.append(self.list, ref)
  36         del self.list[0]
  37         self.assert_(not list.__contains__(self.list, ref))
  38                           
  39     def testAppend(self):
  40         o = Object()
  41         self.list.append(o)
  42         self.assert_(list.pop(self.list)() is o)
  43 
  44     def testCount(self):
  45         a = Object()
  46         b = Object()
  47         c = Object()
  48         y = {3:a, 5:b, 8:c}
  49 
  50         for n, o in y.items():
  51             for x in range(n):
  52                 list.append(self.list, weakref.ref(o))
  53 
  54         for n, o in y.items():
  55             x = self.list.count(o)
  56             self.assertEqual(x, n)
  57 
  58     def testExtend(self):
  59         l = [Object() for x in range(10)]
  60         o = Object()
  61         list.append(self.list, weakref.ref(o))
  62         self.list.extend(l)
  63         self.assertEqual(list.__len__(self.list), 11)
  64         for x in range(10):
  65             self.assert_(list.pop(self.list)() is l.pop())
  66         self.assert_(list.pop(self.list)() is o)
  67 
  68     def testIndex(self):
  69         l = [weakref.ref(Object()) for x in range(10)]
  70         o = Object()
  71         ref = weakref.ref(o)
  72         list.extend(self.list, l)
  73         list.__setitem__(self.list, 4, ref)
  74         self.assertEqual(self.list.index(o), 4)
  75 
  76     def testInsert(self):
  77         l = [weakref.ref(Object()) for x in range(10)]
  78         list.extend(self.list, l)
  79         o = Object()
  80         self.list.insert(5, o)
  81         self.assert_(list.__getitem__(self.list, 5)() is o)
  82 
  83     def testPop(self):
  84         o = Object()
  85         list.append(self.list, weakref.ref(o))
  86         self.assert_(self.list.pop() is o)
  87 
  88     def testRemove(self):
  89         l = [weakref.ref(Object()) for x in range(10)]
  90         list.extend(self.list, l)
  91         o = Object()
  92         ref = weakref.ref(o)
  93         list.insert(self.list, 7, ref)
  94         self.list.remove(o)
  95         self.assert_(not list.__contains__(self.list, ref))
  96 
  97     def testReverse(self):
  98         a, b, c = Object(), Object(), Object()
  99         for o in a, b, c:
 100             list.append(self.list, weakref.ref(o))
 101         self.list.reverse()
 102         for o in a, b, c:
 103             self.assert_(list.pop(self.list)() is o)
 104 
 105     def testSortWithFunc(self):
 106         l = []
 107         f = []
 108         for x in range(10):
 109             o = Object()
 110             o.i = x
 111             f.append(o)
 112             l.append(weakref.ref(o))
 113         random.shuffle(l)
 114 
 115         list.extend(self.list, l)
 116 
 117         def cmpfunc(x, y):
 118             if x.i > y.i: return 1
 119             if x.i == y.i: return 0
 120             if x.i < y.i: return -1
 121 
 122         self.list.sort(cmpfunc)
 123         for x in range(10):
 124             self.assert_(list.pop(self.list)() is f.pop())
 125 
 126     def testSortWithoutFunc(self):
 127 
 128         class Object(object):
 129             def __init__(self, i):
 130                 self.i = i
 131                 
 132             def __lt__(self, other):
 133                 return self.i < other.i
 134 
 135             def __le__(self, other):
 136                 return self.i <= other.i
 137 
 138             def __eq__(self, other):
 139                 return self.i == other.i
 140 
 141             def __ne__(self, other):
 142                 return self.i != other.i
 143 
 144             def __gt__(self, other):
 145                 return self.i > other.i
 146 
 147             def __ge__(self, other):
 148                 return self.i >= other.i
 149         
 150         l = []
 151         f = []
 152         for x in range(10):
 153             o = Object(x)
 154             f.append(o)
 155             l.append(weakref.ref(o))
 156         random.shuffle(l)
 157 
 158         list.extend(self.list, l)
 159 
 160         self.list.sort()
 161         for x in range(10):
 162             self.assert_(list.pop(self.list)() is f.pop())
 163 
 164     def testAdd(self):
 165         o = Object()
 166         list.append(self.list, weakref.ref(o))
 167         l = [1, 2]
 168         f = self.list + l
 169         self.assert_(o in f)
 170 
 171     def testContains(self):
 172         o = Object()
 173         list.append(self.list, weakref.ref(o))
 174         self.assert_(o in self.list)
 175 
 176     def testDelSlice(self):
 177         l = [Object() for x in range(10)]
 178         f = [weakref.ref(o) for o in l]
 179 
 180         list.extend(self.list, f)
 181         del l[2:6]
 182         del self.list[2:6]
 183         while l:
 184             self.assert_(l.pop() is list.pop(self.list)())
 185 
 186     def testEq(self):
 187         l = [Object(), Object(), Object()]
 188         for o in l:
 189             list.append(self.list, weakref.ref(o))
 190         self.assert_(self.list == l)
 191         self.assert_(l == self.list)
 192 
 193 
 194 if __name__ == "__main__":
 195     unittest.main()

Volta para CookBook.


PedroWerneck