Skip to content
python package for named constants (e.g. enums)
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore
.travis.yml
LICENSE_Apache_20
README.rst
named_constants.py
setup.py
test_named_constants.py

README.rst

Overview

This module offers an easy way to define named constants in Python, supporting some simple enum-like use case, as well as arbitrary value types like strings or floats. It is rather simple to use and does not have a big footprint, but supports the following features:

  • Ease of use (a simple class for scoping, plain definitions inside)
  • Enumeration of defined constants
  • Values know their name, i.e. you don't have to guess which meaning the constant value 3 has (e.g. it's name() will be 'blue' and its __repr__ will format as 'Colors.blue')
  • Arbitrary value types (not just integers)
  • Constant-ness (no change after time of definition)

There are unit tests, and the code has been made compatible with both Python 2.x and 3.x at the same time.

Usage

This module is used by deriving from named_constants.Constants in order to define constants in a common namespace:

>>> from named_constants import Constants
>>> class MyConstants(Constants):
...     pi = 3.14159265358
...     e = 2.71828182845
...
>>> print(MyConstants.pi / 2)
1.57079632679

As you can see, the definitions behave as expected, since they are still instances of (subclasses of) the original type. They do offer some additional features, however, most notably that their string representation reveals the constant's name, and that they also have a corresponding name() getter function:

>>> MyConstants.pi
MyConstants.pi
>>> print(MyConstants.pi)
3.14159265358
>>> type(MyConstants.pi)
<class 'named_constants.NamedFloat'>
>>> assert isinstance(MyConstants.pi, float)
>>> MyConstants.pi.name()
'pi'

One common use case will be the definition of some enum-like identifiers:

>>> class Colors(Constants):
...     red, yellow, green, blue, white = range(5)
...
>>> Colors.blue
Colors.blue
>>> Colors.black = None
Traceback (most recent call last):
 ...
TypeError: Constants are not supposed to be changed ex post

The named constants can also be looked up by name or by value:

>>> Colors(3)
Colors.blue
>>> Colors('white') is Colors.white
True

The singleton-like semantics allow you to use equality checks or identity checks, depending on what shall be the result when comparing with the original value:

>>> color1 = 3
>>> color2 = Colors(color1)
>>> color3 = Colors('blue')
>>> color1 == color2
True
>>> color1 is color2
False
>>> color2 is Colors.blue
True
>>> color3 is Colors.blue
True

The namespaces also allow some dict-like introspection:

>>> len(Colors)
5
>>> assert Colors.values() == list(range(5)) == list(Colors)
>>> Colors.has_key('blue')
True
>>> Colors.has_key('purple')
False
>>> for name in Colors.keys():
...     print(name)
red
yellow
green
blue
white
>>> for key, value in Colors.items():
...     print("%10s: %s" % (key, value))
       red: 0
    yellow: 1
     green: 2
      blue: 3
     white: 4

Note that iterating over the namespace (e.g. using the standard keys(), values(), items(), their iter variants (in Python 2), or just for constant in MyConst), the results will be sorted by the values (not the keys/names). This is particularly useful for dumping tables like above.

Note that Colors.has_key(x) is not the same as x in Colors, because the latter equals Colors.has_key(x) or Colors.has_value(x) (that's why has_key exists even in the Python 3 version):

>>> 3 in Colors
True
>>> 17 in Colors
False
>>> 'blue' in Colors
True
>>> 'silver' in Colors
False
>>> Colors.has_value(3)
True
>>> Colors.has_key('blue')
True
>>> Colors.has_key(3)
False
You can’t perform that action at this time.