classes
Steven Taschuk
staschuk at telusplanet.net
Sun Jul 20 14:04:20 EDT 2003
Quoth Pablo:
> [cut]
> >> 2) how to declare a static method
> >
> > class HasStaticMethod:
> > def method(arg0, arg1): # note the lack of "self"
> > # do something with arg0 and arg1
> > method = staticmethod(method)
>
> That's not exactly what I wanted.
[...]
> but Python does not allow to invoke any class method without providing an
> instance of the class object
Sure it does. Allowing that is the purpose of the "staticmethod"
call in Dan's example.
Try it yourself:
>>> class HasStaticMethod(object):
... def mystaticmethod(x, y):
... print x, y
... mystaticmethod = staticmethod(mystaticmethod)
...
>>> HasStaticMethod.mystaticmethod(3, 4)
3 4
No instance of HasStaticMethod exists here.
[...]
> So my problem would be solved if I could create a class which would be
> seen only in its module (something like private class). Then I could
> create an object and simply use it across my application.
[...]
> Is it possible to create a class and forbid its use outside its module?
No, not really. (There's a philosophical reason: Java encourages
the attitude that other programmers can't be trusted to use your
code correctly, while Python encourages the attitude that other
programmers know what they're doing. Thus there's not a lot of
mechanisms in Python to forbid other programmers from doing things
with your code.)
For the particular problem you're interested in -- singletons --
here are a few approaches:
First, use __new__ trickery:
_the_instance = None
class MySingleton(object):
def __new__(self):
global _the_instance
if _the_instance is None:
_the_instance = object.__new__(self)
return _the_instance
Example use:
>>> x = MySingleton()
>>> y = MySingleton()
>>> x is y # same object!
True
In this approach, users create instances of MySingleton as they
would for any other class (rather than by calling a getInstance
classmethod) -- that action just happens to return the same object
always.
One gotcha with this approach can be observed by adding
def __init__(self):
print 'running __init__ on instance %s' % id(self)
Then we see
>>> x = MySingleton()
running __init__ on instance 1075795852
>>> y = MySingleton()
running __init__ on instance 1075795852
>>> x is y
True
As shown, each "instantiation" runs __init__ on the single
instance again. If you have initialization which should occur
only when the single instance is actually created:
_the_instance = None
class MySingleton(object):
def __new__(self):
global _the_instance
if _the_instance is None:
_the_instance = object.__new__(self)
_the_instance._my_init()
return _the_instance
def _my_init(self):
pass # one-time initialization here
(Another possible issue with this approach arises when subclassing
MySingleton. Details left as an exercise.)
Second approach: Use a metaclass. See
<http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/102187>
Third: forget about singletons and use a Borg. See
<http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531>
(With Borgs, multiple instances may exist, but they share state.)
Fourth: rethink the idea that a database connection should be a
singleton. See
<http://c2.com/cgi/wiki?SingletonsAreEvil>
and linked pages for discussion on the merits of singletons.
--
Steven Taschuk 7\ 7'Z {&~ .
staschuk at telusplanet.net Y r --/hG-
(__/ )_ 1^1`
More information about the Python-list
mailing list