I'm coming from a C# background but now doing a fair amount of scientific computing work in Python 3.x., so I'd like some thoughts on how much my style or accent is "weird" by python standards.
In particular, it galls me to no end that there is no such thing as const
in Python. My use case is this: I'm saving *.npz
files (numpy serialized dictionaries of data), passing dicts, writing files, etc. and the dictionary keys, file names, etc. need to have a consistent, dependable naming schema.
It's clear that typing the same magic stupid string in 8 places is Wrong.
So in my module root, i have a file I normally call base.py
:
import os
from collections import namedtuple
from os import path
# This is the tuple that contains operational constants
RuntimeConstants = namedtuple("Const", " ModelDirectoryLabelName \
DefaultModelOutputDirectoryRoot \
ResultDirectoryNameFormat \
PeripheryOutputFilePrefix \
NCOutputFilePrefix \
SummaryPlotFileName \
PeripheryConfigurationName \
ResourceDirectoryName \
StimulusTemplateName")
runtime_consts = RuntimeConstants(ModelDirectoryLabelName=".model-output-root",
DefaultModelOutputDirectoryRoot="model-output",
ResultDirectoryNameFormat="%d %b %y - %H%M",
PeripheryOutputFilePrefix="periphery-output-",
NCOutputFilePrefix="nc-output-",
PeripheryConfigurationName="simulation-configuration.yaml",
SummaryPlotFileName="summary-plots.pdf",
ResourceDirectoryName="resources",
StimulusTemplateName="default_stimulus.yaml"
)
# This is the path of __this file__, which we can then base location on
rootPath = os.path.dirname(os.path.abspath(__file__))
Tuples are immutable; named tuples have semantically meaningful indicies, and now:
In c#, it's pretty normal practice to have one or more Constants
class filled with public static const string Foo = "some magic string value";
, so that's what I've tried to recreate here.
I currently have 4 such namedtuples
in base.py
, which seems like it's on the edge of having too many -- but i don't need any more than this. They're all semantically different -- I group constants by useage association.
Is this common-ish practice?
In the years since I asked this, i have discovered that the actual answer is attrs.
Specifically rebutting my idea of using namedtuple is this explainer.
I would now express what I wanted originally as frozen slotted classes:
import attrs
@attr.s(frozen=True, slots=True)
class ModelParams:
fs = attr.ib(default=1000)
...
# about as close to immutable as you can get.
model_params = ModelParams()
It is not. The standard convention for constants is to just use all-caps names to suggest that the value is constant, and document them as constant.
MODEL_DIRECTORY_LABEL_NAME = ".model-output-root"
DEFAULT_MODEL_OUTPUT_DIRECTORY_ROOT = "model-output"
# etc
The user of your module modifies those values at his own risk.
If the constants are naturally associated with a class, they can be class attributes instead of module-level globals, but it is not common to create a class just to group such values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With