Singleton?
James T. Dennis
jadestar at idiom.com
Sun Jan 27 17:03:02 EST 2002
Jason Orendorff <jason at jorendorff.com> wrote:
> James T. Dennis writes:
>> Would this be considered to be a valid implementation of
>> the GoF "singleton" pattern?
>> [...]
>> My test suite passes, of course. But I'm not sure if this
>> would count as a valid "singleton" though it does seem to
>> exhibit the desire behavior. It this "cheating?" What are
>> the consequences of this approach?
> (grin) Cheating?? Your approach is about as good as any.
> There are many approaches. My favorite, when it's feasible, is:
> class _X:
> """ NOTE: Do not instantiate this class! Use x instead. """
> pass
> x = _X() # singleton instance
This is similar to an option I considered:
class _X:
"""Singleton Shadow Class: Don't Instantiate Directly"""
def __init__(s):
s.instantiatedflag=s
...
class X:
"""Instantiate me so I can call on my shadow"""
# ???
... on the idea that X is sort of a proxy to the real (shadow)
class _X. The proxy would enforce the singleton nature of the
_X (or I could raise some sort SingletonInstantiation exception).
I understand that the main detrimental consequence of my approach
is that my "class" can't be subclassed. My main goal was to
allow multiple attempts at instantiation to occur without error
while still guaranteeing a singleton. What I'd like to do is have
some sort of __instantiate__() member that would allow a class to
return a custom object reference.
I can see the problem: __init__(self, ...) needs a "self" which
is why it can't return a value. If we had an __instantiate__()
(which could NOT have a "self" argument, or any other since those are
appended to the self argument that's passed to __init__() then
we could have it return an object reference (singleton or from a
pool) or raise and exception.
Would that make for a reasonable PEP? Foo.__instantiate__() is
called by: a=Foo() and it can return an object reference or
raise an exception. So the sequence (internally) would go
something like:
parser/engine sees: a=Foo()
it finds the class Foo
if Foo.__instantiate__ exists:
call it
# must return an object reference
else:
instantiate a generic object
# either way we get "self"
if Foo.__init__ exists:
call it with "self" and any args, kwargs, etc
return self (binding/assigning it to a
As I say, this would make singletons trivially easy, we'd just
have an _instantiated member
class Foo:
_instantiated=None
def __instantiate():
if _instantiated:
return _instantiated
else:
Foo._instantiated=Object() ## Generic obj
## ...
... but it would also allow us to have object pools (so we could
easily have some large number of objects which are used, thrown
into the "free" pool and then available for re-use). I surprised
that the GoF didn't have an "Pool" pattern for just this sort of
us; on the notion that instantiating new objects can be expensive
and lead to memory fragmentation (possibly causing excessive GC)
while re-using previously instantiated objects might be considerably
less expensive.
I'm not sure what other uses it might have.
Should I submit that as a PEP? (I don't know anything about the
PEP marshalling process, though I seem PEPs or proto-PEPs shot down
in flames on this newsgroup on a regular basis).
More information about the Python-list
mailing list