473,656 Members | 2,983 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

How to create a limited set of instanceses of a class

For the pure theory sake and mind expansion i got a question.
Experimenting with __new__ i found out how to create a singleton.
class SingleStr(objec t):
def __new__(cls,*ar gs,**kwargs):
instance=cls.__ dict__.get('ins tance')
if instance:
return instance
cls.instance=ob ject.__new__(cl s,*args,**kwarg s)
return cls.instance

What if i need to create no more than 5 (for example) instances of a
class. I guess that would be not much of a problema but there is a
complication. If one of the instances is garbagecollecte d I want to be
able to spawn another instance. Maybe it's difficult to perceive what i
said so think of a limited number of sockets. Wherenever one is freed
it can be captured again.
I believe that this type of the design pattern was described in
"Thinking in Java" but there was a special method finalize()
utilized, that is called every time when gc() is about to clean up an
unreferenced object. By using this method a counter of active instances
could be easily implemented. What is the pythonic approach to this
problema?

Jul 1 '06 #1
6 1648
madpython <ma*******@gmai l.com> wrote:
For the pure theory sake and mind expansion i got a question.
Experimenting with __new__ i found out how to create a singleton.
class SingleStr(objec t):
def __new__(cls,*ar gs,**kwargs):
instance=cls.__ dict__.get('ins tance')
if instance:
return instance
cls.instance=ob ject.__new__(cl s,*args,**kwarg s)
return cls.instance

What if i need to create no more than 5 (for example) instances of a
And what if somebody asks for a 6th one -- raise an exception? or
return a random one of the 5? Ah well, anyway...:
class. I guess that would be not much of a problema but there is a
complication. If one of the instances is garbagecollecte d I want to be
able to spawn another instance. Maybe it's difficult to perceive what i
said so think of a limited number of sockets. Wherenever one is freed
it can be captured again.


Have the class hold weak references to the instances. E.g.:

import weakref
import random

class JustFive(object ):
_counter = 0
_insts = weakref.WeakKey Dictionary()

def __new__(cls):
if len(cls._insts) < 5:
inst = object.__new__( cls)
inst.id = cls._counter
cls._insts[inst] = None
cls._counter += 1
else:
inst = random.choice(c ls._insts.keys( ))
return inst

Testing this for the specified behavior should be done more
systematically, of course, but here's a snippet based only on showing
exactly what's going on...:
if __name__ == '__main__':
samp = [JustFive() for i in range(7)]
def showsamp():
for s in samp: print s.id,
ss = set(s.id for s in samp)
print '{',
for s in sorted(ss): print '%d,'%s,
print '} #%d'%len(ss)
print 'Start with:',
showsamp()
for x in range(10):
i = random.randrang e(len(samp))
print ('@%d,'%i), samp[i].id, '->',
samp[i] = None
newone = JustFive()
samp[i] = newone
print '%d,' % samp[i].id,
showsamp()
A sample run might go, for example...:

Start with: 0 1 2 3 4 4 1 { 0, 1, 2, 3, 4, } #5
@0, 0 -> 5, 5 1 2 3 4 4 1 { 1, 2, 3, 4, 5, } #5
@1, 1 -> 3, 5 3 2 3 4 4 1 { 1, 2, 3, 4, 5, } #5
@6, 1 -> 6, 5 3 2 3 4 4 6 { 2, 3, 4, 5, 6, } #5
@2, 2 -> 7, 5 3 7 3 4 4 6 { 3, 4, 5, 6, 7, } #5
@4, 4 -> 7, 5 3 7 3 7 4 6 { 3, 4, 5, 6, 7, } #5
@4, 7 -> 6, 5 3 7 3 6 4 6 { 3, 4, 5, 6, 7, } #5
@1, 3 -> 7, 5 7 7 3 6 4 6 { 3, 4, 5, 6, 7, } #5
@3, 3 -> 8, 5 7 7 8 6 4 6 { 4, 5, 6, 7, 8, } #5
@6, 6 -> 5, 5 7 7 8 6 4 5 { 4, 5, 6, 7, 8, } #5
@2, 7 -> 6, 5 7 6 8 6 4 5 { 4, 5, 6, 7, 8, } #5

and the point is that the sample always has a set of objects with
exactly 5 separate id values, but the set "migrates" upwards as some
objects happen to be dropped. Well, not always "upwards" as smoothly as
luck would have it in this case, e.g., another run goes:

Start with: 0 1 2 3 4 1 2 { 0, 1, 2, 3, 4, } #5
@1, 1 -> 3, 0 3 2 3 4 1 2 { 0, 1, 2, 3, 4, } #5
@2, 2 -> 4, 0 3 4 3 4 1 2 { 0, 1, 2, 3, 4, } #5
@3, 3 -> 1, 0 3 4 1 4 1 2 { 0, 1, 2, 3, 4, } #5
@1, 3 -> 5, 0 5 4 1 4 1 2 { 0, 1, 2, 4, 5, } #5
@5, 1 -> 5, 0 5 4 1 4 5 2 { 0, 1, 2, 4, 5, } #5
@6, 2 -> 6, 0 5 4 1 4 5 6 { 0, 1, 4, 5, 6, } #5
@2, 4 -> 1, 0 5 1 1 4 5 6 { 0, 1, 4, 5, 6, } #5
@4, 4 -> 7, 0 5 1 1 7 5 6 { 0, 1, 5, 6, 7, } #5
@6, 6 -> 8, 0 5 1 1 7 5 8 { 0, 1, 5, 7, 8, } #5
@3, 1 -> 8, 0 5 1 8 7 5 8 { 0, 1, 5, 7, 8, } #5

here, the objects with ids 0 and 1 just never happen to get dropped.
Alex
Jul 1 '06 #2
madpython wrote:
For the pure theory sake and mind expansion i got a question.
Experimenting with __new__ i found out how to create a singleton.
class SingleStr(objec t):
def __new__(cls,*ar gs,**kwargs):
instance=cls.__ dict__.get('ins tance')
if instance:
return instance
cls.instance=ob ject.__new__(cl s,*args,**kwarg s)
return cls.instance

What if i need to create no more than 5 (for example) instances of a
class. I guess that would be not much of a problema but there is a
complication. If one of the instances is garbagecollecte d I want to be
able to spawn another instance....


This should help. You didn't really say how to pick the result
if there are duplicates, so I just decided for myself. Read up
on the weakref module, it is your friend in this kind of problem.

import weakref, random

class Limited(any_new _style_class):
_held_instances = weakref.WeakVal ueDictionary()
_held_limit = 5
def __new__(class_, *args, **kwargs):
if len(class_._hel d_instances) < class_._held_li mit:
# You could go over here if threading is an issue
instance = super(class_, Limited).__new_ _(
class_, *args, **kwargs)
class_._held_in stances[id(instance)] = instance
return instance
return random.choice(c lass_._held_ins tances.values() )
--Scott David Daniels
sc***********@a cm.org
Jul 1 '06 #3
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=w eakref.WeakValu eDictionary()
def __new__(cls,*ar gs,**kwargs):
if len(cls.__weakr efdict)<5:
instance=super( Limited5,cls)._ _new__(cls,*arg s,**kwargs)
cls.__weakrefdi ct[id(instance)]=instance
return instance
# return random.choice(c ls.__weakrefdic t.values())
return None #no need to pick an instance
class A(Limited5):
counter=0
def __init__(self):
self.instCounte r=self.counter
A.counter+=1
def getId(self):
return id(self)

if __name__=="__ma in__":
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.instCou nter
instList.append (ainst)
print "---------------------------------------------"

#delete and recreate an arbitrary element in the instList
for i in range(len(instL ist)):
instList.remove (instList[random.choice(r ange(len(instLi st)))])
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.instCoun ter
#print "-------",item
print "++++++++++++++ ++++++++++++++"

Jul 2 '06 #4
madpython <ma*******@gmai l.comwrote:
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.
And the latter issue is what the use of weakref in both responses was
about.
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)
Note that this is quite sloppy:

-- test "if ainst is None:" -- no excuse to use just "if ainst:"
-- at the end of the loop ainst remains bound -- "del ainst" to avoid
ainst being an extra reference to the instance

neither of these explains your bug, but -- just tighten up your code,
it's a good idea!-)
>
for i in range(5):
instList.remove (instList[0]) #here the hardref is deleted
SUPER sloppy! Just "del instList[0]" for the same effect much better
obtained.
ainst=A()
while not ainst:
#make shure that ainst is not NoneType
Again, "while ainst is None:" would be far better.
gc.collect()
time.sleep(1) #wait 1 sec for gc() to clean the memory
Useless, gc.collect() is synchronous *AND* only cleans up CYCLIC garbage
anyway -- unless instances of A have reference loops, both lines are
useless (the sleep is useless in ANY case).
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.
Your test code below does NOT do what your code here does! Instead it
removes (in the worst possible way, rather than cleanly, but, no matter)
a RANDOM reference -- which may happen to be the same as "item" had left
over from the previous run... because of a printing loop that is in your
sample below and not here... which is where the sloppiness catches up on
you. Specifically, look at this code from the sample that you had
below:
#delete and recreate an arbitrary element in the instList
for i in range(len(instL ist)):
instList.remove (instList[random.choice(r ange(len(instLi st)))])
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 "*", len(instList), len(A._weakrefd ict)
instList.append (ainst)
for item in instList:
print item.getId()," -- ",item.instCoun ter
#print "-------",item
print "++++++++++++++ ++++++++++++++"
after the printing loop, name 'item' remains bound to the object that is
last element of instList -- so if that one just happens to be the
element you remove in that horrid first line of the main (outer) loop, 5
instances of class A nevertheless remain alive and therefore ainst will
be None forevermore, despite all the useless calls to gc.collect and
sleep.

A decent way to code this functionality would be:

# delete and recreate an arbitrary element in the instList
for i in range(len(instL ist)):
del instList[random.randrang e(len(instList) )]
instList.append (A())
for item in instList:
print item.getId()," -- ",item.instCoun ter
del item
print "++++++++++++++ ++++++++++++++"

It would be nice to also print len(instList) and the length of the
weakref dictionary of class A, to doublecheck things, but you've made
life extremely hard for yourself by naming the latter with TWO leading
underscores instead of one, thus asking Python to name-mangle it to make
it very inconvenient to access. Avoid the two-leading-underscores
construct (use just ONE leading underscore -- no mangling, no problems)
unless and until you are positive that you know exactly what you're
doing and are certain that you need the two underscores in a given
specific case -- do *NOT* "default" to using two underscores and make
life uselessly hard for yourself in terms of introspection and
debugging.

And, read up on such issues as "del somelist[index]" being WAY better
than "somelist.remov e(somelist[index])" and the way names, references,
objects and garbage collection work in Python...
Alex
Jul 2 '06 #5
Thanks, Alex, again. The lesson has been taught. I appreciate very much
you spent time trying to help. Indeed the culprit of that infrequent
infinite loops was that bound reference "item" in the printing
loop. But frankly i thought that it only existed inside that loop.
Apparently I was wrong and glad that it was revealed.
I guess unless there is something to add here the problem is solved
and subject is closed. Thanks everyone who took their time to ponder on
it. I hope it was as much educational for you as it was for me.

Jul 2 '06 #6
madpython <ma*******@gmai l.comwrote:
Thanks, Alex, again. The lesson has been taught. I appreciate very much
you spent time trying to help. Indeed the culprit of that infrequent
infinite loops was that bound reference "item" in the printing
loop. But frankly i thought that it only existed inside that loop.
Apparently I was wrong and glad that it was revealed.
Right -- a loop per se (be it a while loop or a for loop), just like an
if statement or a try statement, is NOT a separate scope from the code
around it (neither is a list comprehension); _functions_ are separate
scopes, and so are genexps.
Alex
Jul 2 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
2179
by: Ernesto | last post by:
Hi everybody: I have the following typedefs: typedef unsigned char UCHAR; typedef unsigned char BYTE; I am implementing a class String with the following operators overloaded: String& operator+ (const UCHAR& myChar);
7
8850
by: dog | last post by:
I've seen plenty of articles on this topic but none of them have been able to solve my problem. I am working with an Access 97 database on an NT4.0 machine, which has many Access reports. I want my users to be able to select a report, click on a command button on a form, which will then automatically create the report as a pdf file and save it to the user's machine. I am using Adobe Acrobat (5.0 I think) and have Adobe Distiller as a
1
4950
by: Patrick Blackman | last post by:
Has anyone used CreateWindowEX API to create a control in C#? I want to create the Richtextbox control using this method so I can have better control over the underlying interfaces to substantial extend the functionality. Any Ideas would be appreciated. What I really want to do is create the control with a limited exposure of properties, if I subclass the RictextBox in .net , there are just too many properties exposed. In VB we had the...
2
2540
by: Lan H. Nguyen | last post by:
I am trying to create FTP virtual directory in an ASP.net page but got an access denied error. I know that the page is running under IUSR_ account with limited rights. I'd like to create a new thread with god like rights to do this. Can anyone help? Thanks very much in advance, Lan
8
1374
by: Thorsten Ottosen | last post by:
Dear all, I'm new to C#, so forgive my stupid question. In my question to avoid boilerplate code, I was wondering if I could use attributes to generate some code for me. For example public class Foo
5
2927
by: Roy Gourgi | last post by:
Hi, I am used to working in Visual FoxPro and I would like to be able to create a database and store and retrieve information from it. What is the simplest way to do it and what should I be using as there are many choices to choose from. My database will contain a lot of records. TIA
5
7619
by: moondaddy | last post by:
I want to create a custom UI element which will be a custom rectangle object in a c# XAML application. I'm new to XAML and c# as most of my experience has been using vb with sql. I'm building a simple Visio type app where I can drag rectangles on a canvas to create diagrams. for now I don't need fancy shapes so I'll just start with a rectangle class where I can add custom properties to it such as where lines are connected to it, etc. ...
3
8316
by: mark4asp | last post by:
Stack of limited size containing unique items? Hi guys, How would I implement a stack of limited size containing unique items? For example. Suppose my stack has . I add 2 to it and it is now . Now I want to add 5 to the unique item stack so it should now be: . The item added is pulled from the stack, then pushed. The stack should also have a maximum size of 4 items. I add 4 and 7
1
1619
by: DR | last post by:
what are the memory caps for threads running as a CLR stored procedure executed by sql server 2005? is it limited by OS only or also by sql servers memory limits? e.g. lets say my clr stored procedure is executed by sql server 2005 then it creates 10 threads and each thread builds a giant array on the stack, is the limits of each array limited by sql server or the os? do these clr stored procedures run inside the sql server address space or...
0
8296
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8816
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8497
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7310
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6162
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5627
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4150
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4299
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
1928
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.