how to save frequently used physical constants in python

Question

I would like to have a place for my physical constants.

The following answer is already a starting point: How-to import constants in many files

So I have a seperate file called constants.py which I import into my projects.

Now, i would like to save and access additional information:

  • units
  • documentation

The resulting interface should be like:

import constants as c

print c.R
>>> 287.102
print c.R.units
>>> J/(kg K)
print c.R.doc
>>> ideal gas constant

Calculations should use c.R to access the value.

It is basically a class, which behaves like the float class but holds two additional strings: units and documentation. How can this be designed?


Show source
| class   | python   | constants   2017-01-07 16:01 2 Answers

Answers ( 2 )

  1. 2017-01-07 16:01

    I recommend using the json library, which will allow you to store your constant values in a readable and modifiable format.

    Using @Daniel's Constant class which inherits from float and adds your custom attributes, you can load all your constants at once into a new Constants object.

    You can then get these attributes as c.R to access the value.

    Complete file:

    #!/usr/bin/env python
    import json
    
    class Constant(float):
        def __new__(cls, value):
            self = float.__new__(cls, value["value"])  # KeyError if missing "value"
            self.units = value.get("units", None)
            self.doc = value.get("doc", None)
            return self
    
    class Constants():
        # load the json file into a dictionary of Constant objects
        def __init__(self):
            with open("constants.json") as fh:
                json_object = json.load(fh)
    
            # create a new dictionary
            self.constants_dict = {}
            for constant in json_object.keys():
                # put each Constant into it
                self.constants_dict[constant] = Constant(json_object[constant])
    
        # try to get the requested attribute
        def __getattr__(self, name):
            # missing keys are returned None, use self.constants_dict[name]
            # if you want to raise a KeyError instead
            return self.constants_dict.get(name, None)
    
    c = Constants()
    print c.R         # 287.102
    print c.R.doc     # ideal gas constant
    print c.R + 5     # 292.102
    print c.F.units   # C mol-1
    print c.missing   # None
    

    Example constants.json:

    {
        "R": {
            "value": 287.102,
            "units": "J/(kg K)",
            "doc": "ideal gas constant"
        },
        "F": {
            "value": 96485.33,
            "units": "C mol-1",
            "doc": "Faraday contant"
        }
    }
    
  2. 2017-01-07 16:01

    Inheriting from class float, you have to overwrite the __new__-method:

    class Constant(float):
        def __new__(cls, value, units, doc):
            self = float.__new__(cls, value)
            self.units = units
            self.doc = doc
            return self
    
    R = Constant(287.102, "J/(kg K)", "deal gas constant")
    
    print R, R * 2
    >>> 287.102 574.204
    print R.units
    >>> J/(kg K)
    print R.doc
    >>> ideal gas constant
    
◀ Go back