【问题标题】:using namedtuples as de facto consts -- clever or stupid?使用 namedtuples 作为事实上的常量——聪明还是愚蠢?
【发布时间】:2016-07-17 02:25:09
【问题描述】:

我来自 C# 背景,但现在在 Python 3.x 中做了大量的科学计算工作,所以我想了解一下我的风格或口音在多大程度上按照 python 标准是“奇怪的”。

尤其是,Python 中没有 const 这样的东西,这让我感到很痛苦。我的用例是这样的:我正在保存*.npz 文件(numpy 序列化数据字典)、传递字典、写入文件等,并且字典键、文件名等需要具有一致、可靠的命名模式。

很明显,在 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"; 是很正常的做法,所以这就是我在这里尝试重新创建的内容。

我目前在base.py 中有 4 个这样的namedtuples,这似乎已经处于拥有太多的边缘——但我不需要更多。它们在语义上都是不同的——我通过使用关联对常量进行分组。

这是常见的做法吗?

【问题讨论】:

标签: python coding-style constants


【解决方案1】:

自从我问这个问题以来的几年里,我发现实际答案是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()

【讨论】:

    【解决方案2】:

    事实并非如此。常量的标准约定是只使用全大写名称来暗示该值是常量,并将它们记录作为常量。

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

    您的模块的用户修改这些值需要自己承担风险。

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

    【讨论】:

    • 确切地说,我还没有创建一个类,但我已将所有全局常量分组到一个文件中。对于这个应用程序,我是我自己的主要用户——但很明显,我有一些关于仅声明字符串的残留问题。
    猜你喜欢
    • 2016-05-04
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 2011-06-09
    • 2010-09-18
    • 1970-01-01
    相关资源
    最近更新 更多