named_constants

python package for named constants (e.g. enums)

APACHE-2.0 License

Downloads
744
Stars
18
Committers
1

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