marou
marou

Reputation: 115

how to save frequently used physical constants in python

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:

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?

Upvotes: 3

Views: 1394

Answers (2)

ti7
ti7

Reputation: 18792

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"
    }
}

Upvotes: 1

Daniel
Daniel

Reputation: 42748

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

Upvotes: 5

Related Questions