473,399 Members | 3,106 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,399 software developers and data experts.

Singleton-like pattern

I need to implement an object that behaves just like imutable objects,
like int, str and tuple: if you create two objects with the same value
at the same time, you get the same object, like a singleton, but
instead of storing a unique object, store a set of objects, with no
duplicates. I don't know if this is a common pattern (and if there's a
name for it), but I remember reading something about it some time
ago... the ASPN cookbook has some similar patterns, but none works for
me...

I know there are several ways to implement this, but I think this
metaclass approach is more elegant than using __new__ and
inheritance... at least it solves my problem (I'm working on a card
game) but I am sure that there are better ways to do it... I could not
find any other value suitable as a key and using str(args) + str(kwds)
is ugly and easy to break...
class MultiSingleton(type):
def __call__(cls, *args, **kwds):
cache = cls.__dict__.get('__cache__')
if cache is None:
cls.__cache__ = cache = {}
tag = str(args) + str(kwds)
if tag in cache:
return cache[tag]
obj = object.__new__(cls)
obj.__init__(*args, **kwds)
cache[tag] = obj
return obj
Any help will be much appreciated... thanks in advance

Pedro Werneck
Jul 18 '05 #1
8 1597
pe***********@bol.com.br (Pedro Werneck) wrote in message news:<ef**************************@posting.google. com>...
I need to implement an object that behaves just like imutable objects,
like int, str and tuple: if you create two objects with the same value
at the same time, you get the same object, like a singleton, but
instead of storing a unique object, store a set of objects, with no
duplicates. I don't know if this is a common pattern (and if there's a
name for it), but I remember reading something about it some time
ago... the ASPN cookbook has some similar patterns, but none works for
me...

I know there are several ways to implement this, but I think this
metaclass approach is more elegant than using __new__ and
inheritance... at least it solves my problem (I'm working on a card
game) but I am sure that there are better ways to do it... I could not
find any other value suitable as a key and using str(args) + str(kwds)
is ugly and easy to break...
class MultiSingleton(type):
def __call__(cls, *args, **kwds):
cache = cls.__dict__.get('__cache__')
if cache is None:
cls.__cache__ = cache = {}
tag = str(args) + str(kwds)
if tag in cache:
return cache[tag]
obj = object.__new__(cls)
obj.__init__(*args, **kwds)
cache[tag] = obj
return obj
Any help will be much appreciated... thanks in advance

Pedro Werneck


"memoize" is a possible name for this. Notice that the metaclass is a
bit of overkill, you may well use a simple function for this job.
About the issue of finding a suitable key, in the same situation I have
used the tuple (args,kw) as key. But me too I would like to ask if this is a
good idea. What's the custom solution for getting a good key from
a dictionary ?
Michele
Jul 18 '05 #2
On 1 Aug 2003 09:15:34 -0700, mi**@pitt.edu (Michele Simionato) wrote:
pe***********@bol.com.br (Pedro Werneck) wrote in message news:<ef**************************@posting.google. com>...
I need to implement an object that behaves just like imutable objects,
like int, str and tuple: if you create two objects with the same value
at the same time, you get the same object, like a singleton, but
instead of storing a unique object, store a set of objects, with no
duplicates. I don't know if this is a common pattern (and if there's a
name for it), but I remember reading something about it some time
ago... the ASPN cookbook has some similar patterns, but none works for
me...

I know there are several ways to implement this, but I think this
metaclass approach is more elegant than using __new__ and
inheritance... at least it solves my problem (I'm working on a card
game) but I am sure that there are better ways to do it... I could not
find any other value suitable as a key and using str(args) + str(kwds)
is ugly and easy to break...
class MultiSingleton(type): class MultiSingleton(object): def __call__(cls, *args, **kwds): def __new__(cls, *args, **kwds): cache = cls.__dict__.get('__cache__')
if cache is None:
cls.__cache__ = cache = {}
tag = str(args) + str(kwds) tag = '%r%r'% (args, kwds) # might be an alternative if tag in cache:
return cache[tag]
obj = object.__new__(cls)
obj.__init__(*args, **kwds)
cache[tag] = obj
return obj
Any help will be much appreciated... thanks in advance

Pedro Werneck
"memoize" is a possible name for this. Notice that the metaclass is a
bit of overkill, you may well use a simple function for this job.

Why not just change as above, and sublass to inherit the behavior
(and create subclass-specific caches) ?
About the issue of finding a suitable key, in the same situation I have
used the tuple (args,kw) as key. But me too I would like to ask if this is a
good idea. What's the custom solution for getting a good key from
a dictionary ?

Does (args,kw) work in general? IWT you could easily get something unhashable?
IWT using a tuple of actual args may also be a bad idea since it would prevent callers'
temp args from being garbage collected. I use repr to avoid that, maybe mistakenly?

Regards,
Bengt Richter
Jul 18 '05 #3
Michele Simionato wrote:
About the issue of finding a suitable key, in the same situation I have
used the tuple (args,kw) as key.
Surely not? Perhaps you meant tuple(args,tuple(kw.items())) ? It gets
rid of the unhashable kw dict.

But me too I would like to ask if this is a
good idea. What's the custom solution for getting a good key from
a dictionary ?


Howabout cPickle.dumps((args,kwargs),1)?
--
CARL BANKS
Jul 18 '05 #4
On 1 Aug 2003, Bengt Richter wrote:
class MultiSingleton(type): class MultiSingleton(object): def __call__(cls, *args, **kwds): def __new__(cls, *args, **kwds): cache = cls.__dict__.get('__cache__')
if cache is None:
cls.__cache__ = cache = {}
tag = str(args) + str(kwds) tag = '%r%r'% (args, kwds) # might be an alternative if tag in cache:
return cache[tag]
obj = object.__new__(cls)
obj.__init__(*args, **kwds)
cache[tag] = obj
return obj

This is exactly what I did at first... I only changed it to a metaclass
because I was adding it to a module that already contain some other
metaclasses I use; I think it's more elegant as I said before... a
'quick and dirty' benchmark with the timeit module returned the
folowing results, and in this project I will be dealing with a database
of 7000+ items, this 20% bit may help a little:

__metaclass__:
[39.744094967842102, 40.455733060836792, 42.027853965759277]

__new__:
[47.914013981819153, 48.721022009849548, 49.430392026901245]
On 1 Aug 2003, Michele Simionato wrote:
"memoize" is a possible name for this. Notice that the metaclass is a
bit of overkill, you may well use a simple function for this job.
Hey... you wrote such a good article on python metaclasses and now don't
want people to use them ? :)
Does (args,kw) work in general? IWT you could easily get something unhashable?
IWT using a tuple of actual args may also be a bad idea since it would prevent callers'
temp args from being garbage collected. I use repr to avoid that, maybe mistakenly? About the issue of finding a suitable key, in the same situation I have
used the tuple (args,kw) as key. But me too I would like to ask if this is a
good idea. What's the custom solution for getting a good key from
a dictionary ?


Actually, (args, kw) doesn't work at all, even if you only get hashable
arguments... the 'kw' dict invalidate it as a key... besides, there's the
garbage collection problem, as Bengt Richter mentioned...

The "%r%r"%(args, kwds) works, as well as str((args, kwds))), but it
breaks if you get as argument an object with the default __repr__, as
the object id may be different, even if they are equal. Overriding __repr__
and returning a real representation avoids this problem.

Thanks for your time.

Pedro Werneck
Jul 18 '05 #5
pe***********@bol.com.br (Pedro Werneck) wrote in message news:<ef**************************@posting.google. com>...
On 1 Aug 2003, Bengt Richter wrote:
> class MultiSingleton(type): class MultiSingleton(object):> def __call__(cls, *args, **kwds): def __new__(cls, *args, **kwds):> cache = cls.__dict__.get('__cache__')
> if cache is None:
> cls.__cache__ = cache = {}
> tag = str(args) + str(kwds) tag = '%r%r'% (args, kwds) # might be an alternative> if tag in cache:
> return cache[tag]
> obj = object.__new__(cls)
> obj.__init__(*args, **kwds)
> cache[tag] = obj
> return obj
This is exactly what I did at first... I only changed it to a metaclass
because I was adding it to a module that already contain some other
metaclasses I use; I think it's more elegant as I said before... a
'quick and dirty' benchmark with the timeit module returned the
folowing results, and in this project I will be dealing with a database
of 7000+ items, this 20% bit may help a little:

__metaclass__:
[39.744094967842102, 40.455733060836792, 42.027853965759277]

__new__:
[47.914013981819153, 48.721022009849548, 49.430392026901245]
On 1 Aug 2003, Michele Simionato wrote:
"memoize" is a possible name for this. Notice that the metaclass is a
bit of overkill, you may well use a simple function for this job.
Hey... you wrote such a good article on python metaclasses and now don't
want people to use them ? :)


Maybe it is because I know them that I don't want to abuse them ;)
Consider also that not everybody knows about metaclasses, and
I want my code to be readable to others; finally, there is
Occam's rasor argument (i.e. do not use metaclasses without necessity).
Does (args,kw) work in general? IWT you could easily get something unhashable?
IWT using a tuple of actual args may also be a bad idea since it would prevent callers'
temp args from being garbage collected. I use repr to avoid that, maybe mistakenly?

About the issue of finding a suitable key, in the same situation I have
used the tuple (args,kw) as key. But me too I would like to ask if this is a
good idea. What's the custom solution for getting a good key from
a dictionary ?


Actually, (args, kw) doesn't work at all, even if you only get hashable
arguments... the 'kw' dict invalidate it as a key... besides, there's the
garbage collection problem, as Bengt Richter mentioned...


Yes, as I replied to Carl Banks, actually I have got problems with
(args,kw) and I think at the end I used args+tuple(kw.iteritems()),
but I had forgotten at the time of the posting.
The "%r%r"%(args, kwds) works, as well as str((args, kwds))), but it
breaks if you get as argument an object with the default __repr__, as
the object id may be different, even if they are equal. Overriding __repr__
and returning a real representation avoids this problem.

Thanks for your time.

Pedro Werneck

Michele
Jul 18 '05 #6
Quoth Michele Simionato:
[...]
Actually you are right, I remember now that I got problems with
(args,kw) and at the end I used args,tuple(kw.items()). But I was
ensure if this was a good solution.


I'd worry about the order of kw.items().

--
Steven Taschuk Aral: "Confusion to the enemy, boy."
st******@telusplanet.net Mark: "Turn-about is fair play, sir."
-- _Mirror Dance_, Lois McMaster Bujold

Jul 18 '05 #7
Steven Taschuk <st******@telusplanet.net> wrote in message news:<ma**********************************@python. org>...
Quoth Michele Simionato:
[...]
Actually you are right, I remember now that I got problems with
(args,kw) and at the end I used args,tuple(kw.items()). But I was
ensure if this was a good solution.


I'd worry about the order of kw.items().


Yes, indeed. Also, the args tuple can contain nested dictionaries and
become unhashable; in such a case I should recursively flatten all
the dictionaries to tuples, taking in account the ordering.
To much work for me ...I have really to look at the cPickle solution.
How does it solve the ordering issue?

Michele
Jul 18 '05 #8
Michele Simionato wrote:
Steven Taschuk <st******@telusplanet.net> wrote in message news:<ma**********************************@python. org>...
Quoth Michele Simionato:
[...]
> Actually you are right, I remember now that I got problems with
> (args,kw) and at the end I used args,tuple(kw.items()). But I was
> ensure if this was a good solution.


I'd worry about the order of kw.items().


Yes, indeed. Also, the args tuple can contain nested dictionaries and
become unhashable; in such a case I should recursively flatten all
the dictionaries to tuples, taking in account the ordering.
To much work for me ...I have really to look at the cPickle solution.
How does it solve the ordering issue?

Unfortunately, not well.
b = { 1: 1, 9: 1 }
b {1: 1, 9: 1} c = { 9: 1, 1: 1 }
c {9: 1, 1: 1} from cPickle import dumps
dumps(b) '(dp1\nI1\nI1\nsI9\nI1\ns.' dumps(c)

'(dp1\nI9\nI1\nsI1\nI1\ns.'

--
CARL BANKS
"You don't run Microsoft Windows. Microsoft Windows runs you."
Jul 18 '05 #9

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

Similar topics

2
by: Sean Dettrick | last post by:
Hi, apologies for yet another Singleton posting. From reading around previous postings etc, I've cobbled together two Singleton template definitions - one that returns a reference, and one that...
10
by: E. Robert Tisdale | last post by:
Could somebody please help me with the definition of a singleton? > cat singleton.cc class { private: // representation int A; int B; public: //functions
16
by: cppaddict | last post by:
Hi, In this tutorial on singleton class in C++ (http://gethelp.devx.com/techtips/cpp_pro/10min/10min0200.asp) the author gives two implementations of a simple singleton class, claiming that...
1
by: Jim Strathmeyer | last post by:
So I'm trying to implement a singleton template class, but I'm getting a confusing 'undefined reference' when it tries to link. Here's the code and g++'s output. Any help? // singleton.h ...
1
by: Capstar | last post by:
Hi NG, I was reading about Singletons on devX. http://gethelp.devx.com/techtips/cpp_pro/10min/10min0200.asp This is their class: class Singleton { public: static Singleton* Instance();
3
by: Harry | last post by:
Hi ppl I have a doubt on singleton class. I am writing a program below class singleton { private: singleton(){}; public: //way 1
6
by: Manuel | last post by:
Consider the classic singleton (from Thinking in C++): ----------------------------------------------------- //: C10:SingletonPattern.cpp #include <iostream> using namespace std; class...
5
by: Rich | last post by:
The following code produced a singleton object with application scope when it should have had page scope: public class Singleton { private static Singleton uniqueInstance = null; private...
3
by: Raider | last post by:
I need to have one object for each template argument(s) used. For example, I need to have one object of int. I tried the following code and it gives me all I want with Visual C++ 7.1. But is it...
3
by: stevewilliams2004 | last post by:
I am attempting to create a singleton, and was wondering if someone could give me a sanity check on the design - does it accomplish my constraints, and/or am I over complicating things. My design...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
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...
0
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,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
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...
0
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,...
0
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...

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.