I want to create a module called 'constants.py' that contain all the constants specific to my system.
To offer flexibility I would like to be able to access the constants directly like this:
constants.power_1
constants.power_2
constants.data_rate_1
constants.data_rate_2
...
because it is short, or access the constants through a dictionary like this:
constants['system_1']['power']
constants['system_2']['power']
constants['system_1']['data_rate']
constants['system_2']['data_rate']
...
because it is useful when sometimes I use a constant inside a loop like this:
systems = ['system_1', 'system_2']
for system in systems:
power = constants[system]['power']
var_2 = var_1 * power
My problem is that I cannot use both methods at the same time.
What I can do:
Option 1. Forget about accessing a constant like constants.power_1
, and have only a dictionary like constants['power_1']
. So I declare them like this in 'constants.py':
constants['power_1'] = 10
constants['system_1']['power'] = constants['power_1']
and use them like this:
from constants import *
var_2 = var_1 * constants['power_1']
var_2 = var_1 * constants['system_1']['power']
Cons:
import *
, even if I import only one dictionary, I prefer a simple import.['']
).Option 2. Use an intermediate name for my dictionary. So I declare them like this in 'constants.py':
power_1 = 10
varname['system 1']['power'] = power_1
and use them like this:
import constants
var_2 = var_1 * constants.power_1
var_2 = var_1 * constants.varname['system 1']['power']
Cons:
varname
, because it is not necessary (I could put system
, but it is redundant).Do you see another way to solve this?
To be honest, if you wanted to do this I would recommend creating a class-based structure, that will provide a dictionary-like structure for hierarchical constants, and a flat namespace for individual constants.
Constants.py could look something like
class Constants:
def __init__(self):
# flat - you can also maybe load this from a JSON so you don't touch this often
self._flat_constants = {
"power_1": 10,
"power_2": 20,
"data_rate_1": 100,
"data_rate_2": 200,
}
# heirachy
self._nested_constants = {
"system_1": {
"power": self._flat_constants["power_1"],
"data_rate": self._flat_constants["data_rate_1"],
},
"system_2": {
"power": self._flat_constants["power_2"],
"data_rate": self._flat_constants["data_rate_2"],
},
}
def __getitem__(self, key):
# First look through the flat ones
if key in self._flat_constants:
return self._flat_constants[key]
# Then check nested ones
if key in self._nested_constants:
return self._nested_constants[key]
raise KeyError(f"Constant '{key}' not found.")
def __getattr__(self, name):
# Allow direct access to flat constants
if name in self._flat_constants:
return self._flat_constants[name]
raise AttributeError(f"'Constants' object has no attribute '{name}'")
Then you can just use it by initializing wherever you plan to, knowing that you can use the dot to access the flat constants (constants.power_1), and the ['system_1]['power']
to access the nested ones.
Tip: If you eventually decide to load from a JSON, you should add some logic to raise an exception if duplicates are found in the keys (duplicates are allowed in JSON).