A simple constant type which overrides the base integer type to provide a useful name on str().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | class constant(int):
"""A constant type which overrides base int to provide a useful name on str().
Example:
>>> STATUS_RUNNING = constant(0, 'running')
>>> STATUS_RUNNING
0
>>> str(STATUS_RUNNING)
'running'
>>>
"""
def __new__(cls, value, name, doc=None):
inst = super(constant, cls).__new__(cls, value)
inst._name = name
if doc is not None:
inst.__doc__ = doc
return inst
def __str__(self):
return self._name
def __eq__(self, other):
if isinstance(other, int):
return int(self) == other
if isinstance(other, str):
return self._name == other
return False
def __ne__(self, other):
return not self.__eq__(other)
|
This recipe can be useful in case integer-based constants are part of your public API. Consider the following situation:
>>> from somemodule import get_status, STATUS_RUNNING, STATUS_SLEEPING, STATUS_STOPPED
>>> get_status()
0
>>>
...to figure out what 0 actually means you would end up doing:
>>> status = get_status()
>>> if status == STATUS_RUNNING:
... print 'running'
... elif status == STATUS_SLEEPING:
... print 'sleeping'
... elif status == STATUS_STOPPED:
... print 'stopped'
...
>>>
Instead, you can just do:
>>> from somemodule import get_status
>>> get_status()
0
>>> str(get_status())
'running'
>>>
Both int and str values can be used when comparing for equality (useful for serialization):
>>> st = constant(0, "running")
>>> st == 0
True
>>> st == 'running'
True
Useful idea! Maybe you could write it as a decorator that would work on any class, not just int, because constants could be strings or even objects, rather than int.
If you change the name of the constant, you need change the name in your __init__(), so maybe the class could find the name in the module by itself ?