使用命名元组作为事实上的竞争 - 聪明还是愚蠢?

时间:2016-03-29 13:32:27

标签: python coding-style const

我来自C#背景,但现在在Python 3.x中进行了大量的科学计算工作,所以我想要了解一下我的风格或口音是多少被python标准“怪异”。

特别是,在Python中没有const之类的东西让我无可奈何。我的用例是这样的:我正在保存*.npz个文件(numpy序列化数据字典),传递dicts,写文件等等,字典键,文件名等需要有一致,可靠的命名架构。

很明显,在8个地方输入相同的魔法愚蠢字符串是错误的。

所以在我的模块根目录中,我有一个我通常称之为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__))

元组是不可变的;命名元组具有语义上有意义的指标,现在:

  • 我可以创建多个词典来动态传递数据,但知道他们的键是什么
  • 我可以使用已知文件名和位置来编写文件并检索文件。
  • 重构意味着我只需要在一个地方修改一个魔术字符串。
  • 我知道我的目录在哪里,即使安装了模块。

在c#中,通常的做法是让一个或多个Constants类填充public static const string Foo = "some magic string value";,这就是我在这里尝试重新创建的内容。

我目前在namedtuples中有4个这样的base.py,看起来好像有太多了 - 但我不需要更多。它们在语义上都是不同的 - 我通过用法关联对常量进行分组。

这是常见的做法吗?

2 个答案:

答案 0 :(得分:1)

不是。常量的标准约定是使用全大写字母名称来表示值是常量,记录它们是常量。

MODEL_DIRECTORY_LABEL_NAME = ".model-output-root"
DEFAULT_MODEL_OUTPUT_DIRECTORY_ROOT = "model-output"
# etc

模块的用户会自行修改这些值。

如果常量自然地与类相关联,则它们可以是类属性而不是模块级全局变量,但创建类只是来对这些值进行分组并不常见。

答案 1 :(得分:0)

自从我问了这些年来,我发现实际的答案是attrs

特别反驳我使用namedtuple的想法是this explainer

我现在将最初想要的内容表达为冻结的空缺类:

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()