[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Generic singleton

mk

3/3/2010 6:55:00 PM

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



18 Answers

Arnaud Delobelle

3/3/2010 7:45:00 PM

0

mk <mrkafk@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

3/3/2010 9:12:00 PM

0

Arnaud Delobelle wrote:
> mk <mrkafk@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

Bruno Desthuilliers

3/3/2010 9:35:00 PM

0

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




Jonathan Gardner

3/3/2010 10:18:00 PM

0

On Wed, Mar 3, 2010 at 1:11 PM, mk <mrkafk@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
jgardner@jonathangardner.net

Steven D'Aprano

3/4/2010 2:14:00 AM

0

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

3/4/2010 4:00:00 AM

0

On Wed, Mar 3, 2010 at 5:18 PM, Jonathan Gardner
<jgardner@jonathangardner.net> wrote:
> On Wed, Mar 3, 2010 at 1:11 PM, mk <mrkafk@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

3/4/2010 11:51:00 AM

0

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

3/4/2010 12:21:00 PM

0

Steven D'Aprano <steven@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.bl...

David Bolen

3/4/2010 7:22:00 PM

0

Duncan Booth <duncan.booth@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

3/5/2010 3:33:00 AM

0

On Thu, 04 Mar 2010 12:21:26 +0000, Duncan Booth wrote:

> Steven D'Aprano <steven@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/Singlet...

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