Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Generic singleton

4 views
Skip to first unread message

mk

unread,
Mar 3, 2010, 1:54:52 PM3/3/10
to pytho...@python.org
Hello,

So I set out to write generic singleton, i.e. the one that would do a
singleton with attributes of specified class. At first:

class Singleton(object):

instance = None

def __new__(cls, impclass, *args, **kwargs):
if cls.instance is None:
cls.instance = impclass.__new__(impclass, *args, **kwargs)
return cls.instance

s1 = Singleton(dict)
s2 = Singleton(dict)

s1['spam']='wonderful'

print s1, s2
print id(s1) == id(s2)


Now, this works. But this obviously doesn't allow class of singleton to
be changed, or a new singleton for another class to be created. So:


class Singleton(object):

instd = {}

def __new__(cls, impclass, *args, **kwargs):
impid = id(impclass)
if not cls.instd.has_key(impid):
cls.instd[impid] = impclass.__new__(impclass, *args, **kwargs)
return cls.instd[impid]

s1 = Singleton(dict)
s2 = Singleton(dict)
s1['spam']='wonderful'


s3 = Singleton(list)
s4 = Singleton(list)
s3.append('eggs')

print id(s1) == id(s2)
print id(s3) == id(s4)

print s1, s2, s3, s4


Questions:

1. Is this safe? That is, does every builtin class have unique id? I
have found this in docs:

hashable
..
All of Python�s immutable built-in objects are hashable, while no
mutable containers (such as lists or dictionaries) are.

Well ok, hashable they're not; but apparently at least dict and list
have id()?

>>> id(list)
135709728
>>> id(dict)
135714560
>>> id(dict)
135714560
>>> c=dict
>>> id(c)
135714560


2. Drawbacks?

3. Better/fancier way to do this?

Regards,
mk

Arnaud Delobelle

unread,
Mar 3, 2010, 2:44:41 PM3/3/10
to
mk <mrk...@gmail.com> writes:
[...]
> hashable
> ..
> All of Python’s immutable built-in objects are hashable, while no

> mutable containers (such as lists or dictionaries) are.
>
> Well ok, hashable they're not; but apparently at least dict and list
> have id()?

lists and dicts are not hashable, but their types are:

>>> hash(dict)
4296155808
>>> hash(list)
4296151808

So just use the type as the key to the dictionary you maintain in your
singleton. But the question is what you use your singleton for.

--
Arnaud

mk

unread,
Mar 3, 2010, 4:11:40 PM3/3/10
to pytho...@python.org
Arnaud Delobelle wrote:
> mk <mrk...@gmail.com> writes:
> [...]
>> hashable
>> ..
>> All of Python’s immutable built-in objects are hashable, while no
>> mutable containers (such as lists or dictionaries) are.
>>
>> Well ok, hashable they're not; but apparently at least dict and list
>> have id()?
>
> lists and dicts are not hashable, but their types are:

Oh.

>>>> hash(dict)
> 4296155808
>>>> hash(list)
> 4296151808
>
> So just use the type as the key to the dictionary you maintain in your
> singleton.

Hmm I have tested it and it seems to work.

> But the question is what you use your singleton for.

Well, partly this was for sake of learning; but partially I was thinking
whether singleton as such may be useful for implementing "global queue
of tasks" for worker threads in a large program: instead of handing down
over and over the same reference to the global queue of tasks, classes
or functions could call Singleton() and be done with it.

Or I could make my life simpler and use global variable. :-)

I will soon need to write such program, with remote calls from pyro
(most probably), many worker threads, short-running jobs and
long-running jobs, etc.


Regards,
mk

Jonathan Gardner

unread,
Mar 3, 2010, 5:18:00 PM3/3/10
to mk, pytho...@python.org
On Wed, Mar 3, 2010 at 1:11 PM, mk <mrk...@gmail.com> wrote:
>
> Or I could make my life simpler and use global variable. :-)
>

Ding ding ding!

90% of Design Patterns is making Java suck less.

Other languages don't necessarily suffer from Java's design flaws.

--
Jonathan Gardner
jgar...@jonathangardner.net

Bruno Desthuilliers

unread,
Mar 3, 2010, 4:34:46 PM3/3/10
to
mk a �crit :

>
> does every builtin class have unique id?

Classes are objects. And every object *within a python process* has it's
own unique id. For a definition of "unique" being "unique amongst the
objects living in the process at a given time" - IOW, if an object is
garbage-collected, it's id can (and will) be reused. For the record, in
CPython, the id value is the address of the (virtual) memory location
where the object lives (not that you could do anything of this info from
within Python - no pointers here).


Steven D'Aprano

unread,
Mar 3, 2010, 9:14:18 PM3/3/10
to
On Wed, 03 Mar 2010 19:54:52 +0100, mk wrote:

> Hello,
>
> So I set out to write generic singleton, i.e. the one that would do a
> singleton with attributes of specified class. At first:

Groan. What is it with the Singleton design pattern? It is one of the
least useful design patterns, and yet it's *everywhere* in Java and C++
world.

I suspect because it allows people to have all the bugs and difficulties
of global variables, while still pretending to be virtuous for not using
global variables. But maybe I'm cynical...

There are a ton of recipes out there for Python Singletons. Don't forget
to check out the Borg pattern, which gives more or less the same effect
using a radically different approach.

Then, my advice is to forget all about them. In my experience, I have
never needed to code my own Singleton class in anything except toy
examples. YMMV.


> print id(s1) == id(s2)

Or, more concisely:

s1 is s2


> class Singleton(object):
>
> instd = {}
>
> def __new__(cls, impclass, *args, **kwargs):
> impid = id(impclass)

Yuck. Why are you using the id of the class as the key, instead of the
class itself?


class Singleton(object):
instd = {}
def __new__(cls, impclass, *args, **kwargs):

if not impclass in cls.instd:
cls.instd[impclass] = impclass.__new__(
impclass, *args, **kwargs)
return cls.instd[impclass]


> Questions:
>
> 1. Is this safe? That is, does every builtin class have unique id? I
> have found this in docs:

Why are you limiting yourself to builtin classes?

ALL objects, whether classes or builtins or strings or ints or instances
of a class you built yourself, have a unique id that lasts for the
lifespan of the object. But that is certainly not what you care about.


--
Steven

Jack Diederich

unread,
Mar 3, 2010, 10:59:55 PM3/3/10
to Jonathan Gardner, pytho...@python.org, mk
On Wed, Mar 3, 2010 at 5:18 PM, Jonathan Gardner
<jgar...@jonathangardner.net> wrote:
> On Wed, Mar 3, 2010 at 1:11 PM, mk <mrk...@gmail.com> wrote:
>>
>> Or I could make my life simpler and use global variable. :-)
>>
>
> Ding ding ding!
>
> 90% of Design Patterns is making Java suck less.
>
> Other languages don't necessarily suffer from Java's design flaws.

The original "Gang of Four" book was about C++ and not Java. The fact
that you can casually assert that "Design Patterns" are about Java
says something not entirely kosher about Java ;)

-Jack

mk

unread,
Mar 4, 2010, 6:50:45 AM3/4/10
to pytho...@python.org
Steven D'Aprano wrote:
> Groan. What is it with the Singleton design pattern? It is one of the
> least useful design patterns, and yet it's *everywhere* in Java and C++
> world.

It's useful when larking about in language internals for learning
purposes, for instance. I don't recall ever actually having significant
need for it.


>> def __new__(cls, impclass, *args, **kwargs):
>> impid = id(impclass)
>
> Yuck. Why are you using the id of the class as the key, instead of the
> class itself?

Bc I didn't know whether it was safe to do that: like Arnaud pointed
out, the *type* of bultins is hashable.

Regards,
mk

Duncan Booth

unread,
Mar 4, 2010, 7:21:26 AM3/4/10
to
Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> wrote:

> On Wed, 03 Mar 2010 19:54:52 +0100, mk wrote:
>
>> Hello,
>>
>> So I set out to write generic singleton, i.e. the one that would do a
>> singleton with attributes of specified class. At first:
>
> Groan. What is it with the Singleton design pattern? It is one of the
> least useful design patterns, and yet it's *everywhere* in Java and C++
> world.

It is also *everywhere* in the Python world. Unlike Java and C++, Python
even has its own built-in type for singletons.

If you want a singleton in Python use a module.

So the OP's original examples become:

--- file singleton.py ---
foo = {}
bar = []

--- other.py ---
from singleton import foo as s1
from singleton import foo as s2
from singleton import bar as s3
from singleton import bar as s4

... and then use them as you wish.

--
Duncan Booth http://kupuguy.blogspot.com

David Bolen

unread,
Mar 4, 2010, 2:21:58 PM3/4/10
to
Duncan Booth <duncan...@invalid.invalid> writes:

> It is also *everywhere* in the Python world. Unlike Java and C++, Python
> even has its own built-in type for singletons.
>
> If you want a singleton in Python use a module.
>
> So the OP's original examples become:
>
> --- file singleton.py ---
> foo = {}
> bar = []
>
> --- other.py ---
> from singleton import foo as s1
> from singleton import foo as s2
> from singleton import bar as s3
> from singleton import bar as s4
>
> ... and then use them as you wish.

In the event you do use a module as a singleton container, I would
advocate sticking with fully qualified names, avoiding the use of
"from" imports or any other local namespace caching of references.

Other code sharing the module may not update things as expected, e.g.:

import singleton

singleton.foo = {}

at which point you've got two objects around - one in the singleton.py
module namespace, and the s1/s2 referenced object in other.py.

If you're confident of the usage pattern of all the using code, it may
not be critical. But consistently using "singleton.foo" (or an import
alias like s.foo) is a bit more robust, sticking with only one
namespace to reach the singleton.

-- David


Steven D'Aprano

unread,
Mar 4, 2010, 10:32:46 PM3/4/10
to
On Thu, 04 Mar 2010 12:21:26 +0000, Duncan Booth wrote:

> Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> wrote:
>
>> On Wed, 03 Mar 2010 19:54:52 +0100, mk wrote:
>>
>>> Hello,
>>>
>>> So I set out to write generic singleton, i.e. the one that would do a
>>> singleton with attributes of specified class. At first:
>>
>> Groan. What is it with the Singleton design pattern? It is one of the
>> least useful design patterns, and yet it's *everywhere* in Java and C++
>> world.
>
> It is also *everywhere* in the Python world. Unlike Java and C++, Python
> even has its own built-in type for singletons.
>
> If you want a singleton in Python use a module.

I was wondering who would be the first to point that out :)

You are, of course, correct that the preferred way to solve the Singleton
problem is with a module. (The other preferred way is with the Borg
pattern, which is kind of a reverse-Singleton.) Using classes works too:
so long as you do not instantiate it, but use it as an object in its own
right, a class is also a singleton.

However, I don't think it's quite right to say that modules *are*
Singletons, although I accept that this is now getting into a tedious
argument about terminology. A singleton is an instance of a class which
can only have a single instance. This is not true of modules:

>>> import string, math
>>> type(string) is type(math)
True
>>> string is math
False

Wikipedia points out that the Singleton pattern is normally understood to
exclude static structures which merely happen to be created once:

"Note the distinction between a simple static instance of a class and a
singleton..."

http://en.wikipedia.org/wiki/Singleton_pattern

Each individual module is a static instance of the module class which
merely happens to be instantiated once. (You can subvert Python's import
machinery to create multiple copies of a module, but normally this
doesn't happen.) So *technically* modules are not singletons, although
they behave just like them and give all the benefits, and disadvantages,
of such. And as you say, the preferred Pythonic solution to the
requirement for a Singleton is usually a module.

Python does have it's own singletons, like None, True and False. For some
reason, they behave quite differently: NoneType fails if you try to
instantiate it again, while bool returns the appropriate existing
singleton:

>>> NoneType = type(None)
>>> NoneType()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'NoneType' instances
>>> bool(45)
True


I wonder why NoneType doesn't just return None?


--
Steven

Steve Howell

unread,
Mar 4, 2010, 11:14:42 PM3/4/10
to
On Mar 4, 7:32 pm, Steven D'Aprano <st...@REMOVE-THIS-

cybersource.com.au> wrote:
>
> Python does have it's own singletons, like None, True and False. For some
> reason, they behave quite differently: NoneType fails if you try to
> instantiate it again, while bool returns the appropriate existing
> singleton:
>
> >>> NoneType = type(None)
> >>> NoneType()
>
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: cannot create 'NoneType' instances>>> bool(45)
>
> True
>
> I wonder why NoneType doesn't just return None?
>

It's an interesting question. Just to elaborate on your example:

>>> type(None)()


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'NoneType' instances

>>> type(True)(False)
False
>>> type(False)(True)
True

I suspect that the answer is just that None is special. There is
probably just no compelling use case where you want to clone None in a
one-liner.

To make None work like True/False in certain use cases you'd want
something like this:

def clone(val):
if val is None:
return None
else:
return type(val)(val)

The same method would work against some non-singletons as well,
although I'm not sure what the desired semantics would actually be:

for value in [None, False, True, 42, [1, 2, 3]]:
print clone(value)

Gregory Ewing

unread,
Mar 5, 2010, 2:33:44 AM3/5/10
to
mk wrote:

> Or I could make my life simpler and use global variable. :-)

Indeed. You actually *have* a global variable already, you've
just hidden it inside another object. That doesn't make it any
less global, though.

If you want to defer creation of the object until the first
time it's used, use a function that creates an instance the
first time it's called. Your Singleton class is really just
an overly elaborate way of implementing such a function.

--
Greg

Terry Reedy

unread,
Mar 5, 2010, 11:57:13 AM3/5/10
to pytho...@python.org
On 3/4/2010 10:32 PM, Steven D'Aprano wrote:

> Python does have it's own singletons, like None, True and False.

True and False are not singletons.

> For some reason, they behave quite differently:

Because they are quite different.

> NoneType fails if you try to instantiate it again,

Because trying 'type(None)()' was probably judged to be more likely to
be a bug than something useful.

> while bool returns the appropriate existing singleton: [sic]

Branching on boolean values (which are no more singletons than 0, 1,
...) is basic to computing.

> I wonder why NoneType doesn't just return None?

What would you have NoneType(x) do? Or the special case NoneType(None)?
The issue has come up as to whether object(x) should ignore or raise.
In 3.x, it raises.
TypeError: object.__new__() takes no parameters
but I believe this is changed from at least some 2.x versions that
ignored (apparently by 'accident').

Terry Jan Reedy

Steven D'Aprano

unread,
Mar 5, 2010, 1:01:11 PM3/5/10
to
On Fri, 05 Mar 2010 11:57:13 -0500, Terry Reedy wrote:

> On 3/4/2010 10:32 PM, Steven D'Aprano wrote:
>
>> Python does have it's own singletons, like None, True and False.
>
> True and False are not singletons.

Duotons? Doubletons?

>>> t1 = bool(1)
>>> t2 = bool(1)
>>> t1 is t2
True
>>> t1 is t2 is bool("this is also true") is bool(['so', 'is', 'this'])
True

They're described as singletons in the PEP, so if you want to argue with
Guido, go right ahead... *grin*

http://www.python.org/dev/peps/pep-0285/

> > For some reason, they behave quite differently:
>
> Because they are quite different.

Well, list("hello world") and list("goodbye now") are quite different
too, but they behave very similarly.


> > NoneType fails if you try to instantiate it again,
>
> Because trying 'type(None)()' was probably judged to be more likely to
> be a bug than something useful.

Obviously people are unlikely to write type(None)(), but they are likely
to do something like:

result = call_some_function(args)
more_code_here()
blah_blah_blah()
new_obj = type(result)()
do_something_with(new_obj)

If result happens to end up being None, I'm not convinced that the caller
would rather have an exception than get the obvious None. If result
happened to be 0, wouldn't you rather get 0 than have it blow up? I don't
see why None should be any different.


> > while bool returns the appropriate existing singleton: [sic]
>
> Branching on boolean values (which are no more singletons than 0, 1,
> ...) is basic to computing.

What does that have to do with the price of fish? I didn't mention
anything about branching on bools.

Once a singleton class has been instantiated the first time, you have a
choice if the user tries to instantiate it again. You can do what
NoneType does, and raise an error. Or you can do what bool does, and
return the existing instance.

Obviously, the behaviour of bool is far more useful. So I wonder why
NoneType doesn't do the same.

>> I wonder why NoneType doesn't just return None?
>
> What would you have NoneType(x) do?

The same thing any function of zero arguments does when it gets called
with one argument.


> Or the special case NoneType(None)?

Why would that be a special case? If NoneType takes no arguments, and you
supply an argument, then it is an error regardless of what that argument
happens to be.


--
Steven

Terry Reedy

unread,
Mar 5, 2010, 4:25:46 PM3/5/10
to pytho...@python.org
On 3/5/2010 1:01 PM, Steven D'Aprano wrote:
> On Fri, 05 Mar 2010 11:57:13 -0500, Terry Reedy wrote:
>
>> On 3/4/2010 10:32 PM, Steven D'Aprano wrote:
>>
>>> Python does have it's own singletons, like None, True and False.
>>
>> True and False are not singletons.
>
> Duotons? Doubletons?

The latter is what I use.


>
>>>> t1 = bool(1)
>>>> t2 = bool(1)
>>>> t1 is t2
> True
>>>> t1 is t2 is bool("this is also true") is bool(['so', 'is', 'this'])
> True
>
> They're described as singletons in the PEP, so if you want to argue with
> Guido, go right ahead... *grin*
> http://www.python.org/dev/peps/pep-0285/

Guido already made the argument ;-) when he followed
'The values False and True will be singletons, like None.'
with 'Because the type has two values, perhaps these should be called
"doubletons"? '. I agree with him here.

By 'singleton', I believe he meant 'keyword constants' with guaranteed
'isness'. Ie, "True is True' and 'False is False', like 'None is None',
are guaranteed in the language def to be true (True) whereas '0 is 0'
and "'' is ''" and '() is ()' are not, even if they happen to be in a
particular implementation.

None of this determine the behavior of the respective null and boolean
classes. If Python had the strict bools that some wanted, bool(x) would
not be legal.

>> > For some reason, they behave quite differently:
>>
>> Because they are quite different.
>
> Well, list("hello world") and list("goodbye now") are quite different
> too, but they behave very similarly.
>
>
>> > NoneType fails if you try to instantiate it again,
>>
>> Because trying 'type(None)()' was probably judged to be more likely to
>> be a bug than something useful.

> Obviously people are unlikely to write type(None)(), but they are likely
> to do something like:
>
> result = call_some_function(args)
> more_code_here()
> blah_blah_blah()
> new_obj = type(result)()
> do_something_with(new_obj)
>
> If result happens to end up being None, I'm not convinced that the caller
> would rather have an exception than get the obvious None. If result
> happened to be 0, wouldn't you rather get 0 than have it blow up? I don't
> see why None should be any different.

This is your strongest argument. It has nothing to do in particular with
(the dubious analogy with) bool. Here is a draft of what you might post
to python-ideas list, or even the tracker.

"
Make type(None) return None

The built-in classes of CPython nearly all follow the (undocumented?)
design rule that if class C has a null instance, C() returns that
(usually unique) null (False) instance. Hence, for instance, one can write

nulls = [type(x)() for x in obs]

to map the objects in obs to their null counterparts. This works for
object of at least the following classes: bool, int, float, complex,
str, bytes, bytearray, tuple, list, set, frozenset, dict,
decimal.Decimal, fractions.Fraction, collections.deque, and
collections.defaultdict.

The one glaring exception is type(None), which raises a TypeError
instead of returning the null value None. This anomaly could be easily
corrected, and the rule documented in, for instance, Lib Ref 5.1. Truth
Value Testing.

Possible objection 1: None is a special singleton.
Answer 1: False is special too, and 'bool() is False' is true.

Possible objection 2: code that depends on no return would break.
Answer 2: at least one other class was changed during the 2.x series to
conform to the rule. (xxx which?)
"

I am pretty sure other classes *were* changed, but cannot specifically
remember which. I would look a bit at the tracker and archives for any
negative pronouncements between posting.

>> > while bool returns the appropriate existing singleton: [sic]
>>
>> Branching on boolean values (which are no more singletons than 0, 1,
>> ...) is basic to computing.
>
> What does that have to do with the price of fish? I didn't mention
> anything about branching on bools.

Every use of 'if', 'and', and 'or' implicitly calls bool, and people
often call it explicitly. There is almost no use case, other than such
as the above, for calling the type of None.

> Once a singleton class has been instantiated the first time, you have a
> choice if the user tries to instantiate it again. You can do what
> NoneType does, and raise an error. Or you can do what bool does, and
> return the existing instance.
>
> Obviously, the behaviour of bool is far more useful.

The behavior of bool is necessary.

> So I wonder why NoneType doesn't do the same.

It predated bool by at least a decade.
The choice was pretty inconsequential, especially then, either way.

>>> I wonder why NoneType doesn't just return None?
>>
>> What would you have NoneType(x) do?
>
> The same thing any function of zero arguments does when it gets called
> with one argument.
>
>> Or the special case NoneType(None)?
>
> Why would that be a special case? If NoneType takes no arguments, and you
> supply an argument, then it is an error regardless of what that argument
> happens to be.

I agree. I asked because there were objections to correcting object(x)
to raise instead of ignore.

Terry Jan Reedy

Steven D'Aprano

unread,
Mar 5, 2010, 6:07:52 PM3/5/10
to
On Fri, 05 Mar 2010 16:25:46 -0500, Terry Reedy wrote:

> On 3/5/2010 1:01 PM, Steven D'Aprano wrote:
>> On Fri, 05 Mar 2010 11:57:13 -0500, Terry Reedy wrote:
>>
>>> On 3/4/2010 10:32 PM, Steven D'Aprano wrote:
>>>
>>>> Python does have it's own singletons, like None, True and False.
>>>
>>> True and False are not singletons.
>>
>> Duotons? Doubletons?
>
> The latter is what I use.

The Wikipedia article on Singleton states that it is acceptable to
generalise "Singleton" to allow multiple instances.

http://en.wikipedia.org/wiki/Singleton_pattern

While Doubleton or even Tripleton sound cute, once you get to large
counts it all starts getting ugly and horrible. "Polyton"? Blah.


[...]


> This is your strongest argument. It has nothing to do in particular with
> (the dubious analogy with) bool. Here is a draft of what you might post
> to python-ideas list, or even the tracker.

Oh, you have misunderstood me. I'm not particularly concerned about
NoneType's behaviour, and certainly not concerned enough to champion the
change against any opposition (let alone through the moratorium!). I
wanted to understand why the difference existed.

Python has at least two other singletons, Ellipsis and NotImplemented,
and both behave like None.

--
Steven

Gregory Ewing

unread,
Mar 5, 2010, 8:39:25 PM3/5/10
to
I think the important difference between None and booleans
wrt singleton behaviour is that things are often compared
with None using "is", so it's quite important that there
only be one instance of NoneType around, and it makes
sense not to give people the false impression that they
can create another one.

Re-using predefined True and False instances is more of
a performance optimisation, however -- they're not usually
compared for identity, or even compared at all for that
matter. So there's no particular reason to disallow
calling bool().

In fact, there's an excellent reason to *allow* calling
it: not only is bool a type, it's also often used as a
function to coerce things to a boolean value:

>>> bool(['hello'])
True

There's no equivalent reason to make NoneType callable,
as coercing something to None makes very little sense.

--
Greg

Gregory Ewing

unread,
Mar 5, 2010, 8:45:58 PM3/5/10
to
Steven D'Aprano wrote:

> While Doubleton or even Tripleton sound cute, once you get to large
> counts it all starts getting ugly and horrible. "Polyton"? Blah.

Tupleton?

--
Greg

0 new messages