Credit: Jürgen Hermann
One way to make a Singleton is to use a private inner class and delegate all operations to a single instance of that class:
class Singleton: """ A Pythonic Singleton """ class _ _impl: """ Implementation of the Singleton class """ def spam(self): """ Just an example method that returns Singleton instance's ID """ return id(self) # The private class attribute holding the "one and only instance" _ _instance = _ _impl( ) def _ _getattr_ _(self, attr): return getattr(self._ _instance, attr) def _ _setattr_ _(self, attr, value): return setattr(self._ _instance, attr, value)
This recipe shows one way to implement the Singleton design pattern in Python (see Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley). A Singleton is a class that makes sure only one instance of it is ever created. Typically, such a class is used to manage resources that by their nature can exist only once. This recipe proposes an alternate approach to accessing such a single instance, which is arguably more Pythonic and more useful than the traditional implementation by a factory function.
This recipe uses the Singleton._ _impl
inner class
as the class that is created only once. Note that
inner classes are nothing special nor
magical in Python, which is quite different from Java, and similar,
instead, to C++. They are just classes that happen to have their
class statement in the body of another class.
The outer class, Singleton
, ensures that exactly
one instance of the inner class, Singleton._ _impl
, is created on demand (i.e., the first time an
instance of Singleton
is created). Each instance
of Singleton
is a proxy to the one instance of
Singleton._ _impl
, using automatic delegation (see
Recipe 5.9) to delegate to it all state and
behavior. (Note that this idiom has also been called
Letter/Envelope by other authors,
such as Coplien; in that naming, Singleton
would
be the Envelope, and Singleton._ _impl
the
Letter.) While the id
of each handle object is
different, the id
of the instance of the inner
class that implements the Singleton behavior is constant.
We can complete the module with the usual self-test idiom and show
this id
behavior:
if _ _name_ _ == '_ _main_ _': s1 = Singleton( ) print id(s1), s1.spam( ) s2 = Singleton( ) print id(s2), s2.spam( )
When we run this module as a script, we get the following output;
note that the second (inner) id
is constant:
8172684 8176268 8168588 8176268
Of course, the inner class isn’t really hidden, as
with almost everything else in Python. If you need to protect against
malicious attempts to access it, you need to use the
rexec
and Bastion
standard
modules and rely on a restricted execution sandbox (but this is
really necessary only when you must run code that you do not trust,
such as code you received from an unknown source).
In addition to the secondary issue of using id
for
Singleton
’s instances, there is a
concrete issue in terms of subclassability. It’s not
really feasible for client code to subclass the real class
(Singleton._ _impl
) in the recipe as presented.
Subclassing the wrapper class (Singleton
) is not
the same thing, since other clients will still get a non-subclassed
version. As the ability to subclass is high on the list of problems
that the Singleton design pattern is supposed to resolve, this is a
significant weakness. See Recipe 5.23 for a
Pythonic solution to this problem.
Recipe 5.9 and Recipe 5.23; Design Patterns: Elements of Reusable Object-Oriented Software, by E. Gamma, R. Helm, R. Johnson, and J. Vlissides (Addison-Wesley, 1995).
Get Python Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.