How to create a limited set of instanceses of a class
madpython
madpython at gmail.com
Sun Jul 2 04:32:09 EDT 2006
Thanks Alex and Scott for your lead. It would've taken me forever
trying to figure it out by myself :)
I am affraid I didn't specify initially one thing and that led to a
confusion: there is no need to pick an instance from the weakref
dictionary, just return None if there are already 5 instances. But on
the other hand if a hardref to an object was deleted, it's place can be
taken by another one.
Here's what i mean (and where the problem is):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#build a list of 5 elements
instList=[]
for i in range(7):
ainst=A()
if ainst:
instList.append(ainst)
for i in range(5):
instList.remove(instList[0]) #here the hardref is deleted
ainst=A()
while not ainst:
#make shure that ainst is not NoneType
gc.collect()
time.sleep(1) #wait 1 sec for gc() to clean the memory
ainst=A() #try again
instList.append(ainst) #new object added
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
the priblem is that ~3 out of 10 times the test part run into infinite
loop because of unsatisfied condition (while not ainst:) - memory
cannot be freed therefore new instance of A isn't permitted.
#!/usr/bin/env python
import weakref,random
import types,gc
import time
class Limited5(object):
__weakrefdict=weakref.WeakValueDictionary()
def __new__(cls,*args,**kwargs):
if len(cls.__weakrefdict)<5:
instance=super(Limited5,cls).__new__(cls,*args,**kwargs)
cls.__weakrefdict[id(instance)]=instance
return instance
# return random.choice(cls.__weakrefdict.values())
return None #no need to pick an instance
class A(Limited5):
counter=0
def __init__(self):
self.instCounter=self.counter
A.counter+=1
def getId(self):
return id(self)
if __name__=="__main__":
instList=[]
# populate the initial list of objects
#make shure that there are only 5 elements
for item in range(7):
ainst=A()
if hasattr(ainst,"getId"):
print ainst.getId()," -- ",ainst.instCounter
instList.append(ainst)
print "---------------------------------------------"
#delete and recreate an arbitrary element in the instList
for i in range(len(instList)):
instList.remove(instList[random.choice(range(len(instList)))])
ainst=A()
while not ainst: #here is an unstable part
ainst=A() #sometimes the loop becomes infinite
print gc.collect() #decpite the explicit call for gc() to
start
time.sleep(1)
print "*",
instList.append(ainst)
for item in instList:
print item.getId()," -- ",item.instCounter
#print "-------> ",item
print "++++++++++++++++++++++++++++"
More information about the Python-list
mailing list