Defining Constants
Credit: Alex Martelli
Problem
You need to define module-level variables that client code cannot accidentally rebind (i.e., named constants).
Solution
In Python 2.1 and later, you can install any instance as if it was a
module. Just put the following in const.py:
class _const:
class ConstError(TypeError): pass
def _ _setattr_ _(self, name, value):
if self._ _dict_ _.has_key(name):
raise self.ConstError, "Can't rebind const(%s)"%name
self._ _dict_ _[name] = value
def _ _delattr_ _(self, name):
if self._ _dict_ _.has_key(name):
raise self.ConstError, "Can't unbind const(%s)"%name
raise NameError, name
import sys
sys.modules[_ _name_ _] = _const( )Now any client code can import const, then bind an
attribute on the const module just once, as
follows:
const.magic = 23
Once the attribute is bound, the program cannot accidentally rebind or unbind it:
const.magic = 88 # would raise const.ConstError del const.magic # would raise const.ConstError
Discussion
In Python, variables can be rebound at will, and modules
don’t let you define special methods such as an
instance’s _ _setattr_ _ to stop
rebinding. An easy solution (in Python 2.1 and later) is to set up an
instance as if it was a module.
In Python 2.1 and later, no check is made to force entries in
sys.modules to be actual module objects. You can
install an instance object there and take advantage of
attribute-access special methods (e.g., to prevent rebinding, to
synthesize attributes on the fly in _ _getattr_ _, and so ...