ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: Constants in Python
Submitter: Alex Martelli (other recipes)
Last Updated: 2001/08/20
Version no: 1.1
Category: OOP

 

4 stars 24 vote(s)


Editors pick

Description:

In Python, any variable can be re-bound at will -- and modules don't let you define special methods such as an instance's __setattr__ to stop attribute re-binding. Easy solution (in Python 2.1 and up): use an instance as "module"...

Source: Text Source

# Put 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
import sys
sys.modules[__name__]=_const()

# that's all -- now any client-code can
import const
# and bind an attribute ONCE:
const.magic = 23
# but NOT re-bind it:
const.magic = 88      # raises const.ConstError
# you may also want to add the obvious __delattr__

Discussion:

In Python 2.1 and up, no check is made any more to force entries in sys.modules to be actually module objects. You can install an instance object there and take advantage of its attribute-access special methods (e.g., as in this snippet, to prevent rebindings; probably more useful, to synthesize attributes on the fly in a __getattr__; whatever...), while still having client-code get the thing with "import whatever". You may also choose to see this as a more Pythonic 'singleton' pattern, or, rather, idiom:-) (but, regarding singleton, also see http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531).



Add comment

Number of comments: 7

good for typechecking too?, philip nunez, 2001/10/25

class typecheck:
    def __init__(self,i):
        self.__type__ = type(i)
    def __setattr__(self,name,value):
        if (name.find('__type__') != 0) and (type(value) != self.__type__):
            raise TypeError, "(%s) is not %s"%(name,self.__type__.__name__)
        self.__dict__[name]=value


if __name__ == '__main__':
    import sys
    try:
        my_int = typecheck(1)
        my_int.x = 3
        my_int.y = 4
        my_int.z = 5
        my_int.h = 'hey'
    except:
        print sys.exc_type, sys.exc_value

    try:
        my_string = typecheck('')
        my_int.s = 'hello'
        my_int.t = 'byebye'
        my_int.u = 3
    except:
        print sys.exc_type, sys.exc_value

Add comment

Don't get carried away, though, Jason Orendorff, 2002/01/07
This is clever, but keep in mind that all the standard modules implement constants this way:

AUDIO_FILE_MAGIC = 0x2e736e64
AUDIO_FILE_ENCODING_MULAW_8 = 1
AUDIO_FILE_ENCODING_LINEAR_8 = 2
AUDIO_FILE_ENCODING_LINEAR_16 = 3
This is much clearer to me. (It runs faster, too.)
Add comment

Michael Shepanski, 2005/04/28
Jason Orendorff, What prevents someone from re-declaring your variables?
Add comment

marijn haverbeke, 2005/06/30
The fact that they are all-uppercase and that the programmer knows that means they are intended to be constants.

If the programmer is a moron, you're screwed anyway. I find all this tendency to try and create libraries/frameworks/utils that can not possibly be used incorrectly a little wrong-headed. Just follow conventions, document, and hope for the best.
Add comment

except:, Stephen Chappell, 2005/10/02
Just make sure that you don't follow that philosophy when you are creating your end product. Your end-user should be able to crash the product. They should, instead, get warnings, if anything.
Add comment

Good philosophy, Thomas Ahle, 2007/06/05
This philosophy is the reason I like python. No need for restrictive private functions and stuff. It should be clear to people that this function is not supposed to be called, but if they REALLY want to, they can do it. And yes, this has nothing to do with the end user, which should of course be protected against h(im|er)self.
Add comment

Error after running the module, chris skoni, 2008/05/20
After typing at prompt >>> : import const I get this error: Traceback (most recent call last): File "", line 1, in -toplevel- import const ImportError: No module named const I also tried >>> import _const (because definition has _const (not const)) - but the same error. So how does it work ? THIS IS THE CODE that I RAN: 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 import sys sys.modules[__name__]=_const() -thanks-cs-
Add comment



Highest rated recipes:

1. A simple XML-RPC server

2. Web service accessible ...

3. a friendly mkdir()

4. SOLVING THE METACLASS ...

5. Povray for python

6. Changing return value ...

7. Implementation of sets ...

8. bag collection class

9. deque collection class

10. Floating Point Simulator




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.