Generic singleton

M

mk

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()?
135714560


2. Drawbacks?

3. Better/fancier way to do this?

Regards,
mk
 
A

Arnaud Delobelle

mk said:
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:
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.
 
M

mk

Arnaud said:
lists and dicts are not hashable, but their types are:
Oh.

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
 
B

Bruno Desthuilliers

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).
 
J

Jonathan Gardner

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.
 
S

Steven D'Aprano

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.
 
J

Jack Diederich

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
 
M

mk

Steven said:
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.

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
 
D

David Bolen

Duncan Booth said:
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
 
S

Steven D'Aprano

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:
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:
Traceback (most recent call last):
True


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

Steve Howell

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:


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:
Traceback (most recent call last):
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)
 
G

Gregory Ewing

mk said:
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.
 
T

Terry Reedy

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
 
S

Steven D'Aprano

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/


Because they are quite different.

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

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.


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.
 
T

Terry Reedy

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.
Well, list("hello world") and list("goodbye now") are quite different
too, but they behave very similarly.
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.
The same thing any function of zero arguments does when it gets called
with one argument.


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
 
S

Steven D'Aprano

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.
 
G

Gregory Ewing

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:
True

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

Gregory Ewing

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

Tupleton?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top