【问题标题】:python mapping with syntax-checkable keys带有语法检查键的 python 映射
【发布时间】:2022-01-24 20:09:21
【问题描述】:

我需要在 python (3.9) 中创建键(字符串、所有合适的 python 标识符)到值的映射。 所有键和值在创建时都是恒定的并且是已知的,我想确保每个键都有一个关联的值。

1.字典

为此想到的第一个想法是使用字典,这带来了一个大问题,即键(在我的情况下)将是字符串。

这意味着每次在字符串文字中手动访问值时我都必须重新键入键,因此 IDE 和类型检查器无法发现拼写错误,在自动完成中建议键名,并且我无法使用它们的实用程序函数来重命名或查找密钥的用法。

1.5 带有常量变量键的字典

对此的天真的解决方案是为每个键或枚举创建一个常量,我认为这不是一个好的解决方案。不仅每次访问都至少添加了一个名称查找,还意味着键定义和值分配是分开的,这可能导致键没有分配值。

2。枚举

这导致了跳过 dict 并使用枚举将键与值直接关联的想法。枚举方便地被语法检查器、自动完成和喜欢的支持,因为它们支持通过“点符号”的属性引用和通过“[]”的订阅。

但是枚举有一个很大的缺点,它要求所有键/枚举成员具有唯一值,并且违反此规则的键将自动转换为别名,这使得输出非常混乱。

我已经考虑过复制 Enum-Code 并删除不需要的位,但是对于这样一个基本问题,这似乎需要付出很多努力。

问题:

所以基本上,我正在寻找的是一种 Python 式的、简洁的方式来定义从字符串键到任意值的(可能不可变的)映射,它支持以下内容:

  • 可迭代(通过键)
  • 具有相同值的键不会相互干扰
  • 键必须具有关联的值
  • 语法检查器、自动完成、重构等会考虑键。

使用它的首选方法是在 python 源文件中定义它,但如果解决方案支持将数据写入文本文件(json 格式或 ini 或类似格式)的简单方法,那将是一个很好的奖励并从这样的文件创建一个新实例。

您将如何做到这一点以及为什么要选择特定的解决方案?

【问题讨论】:

    标签: python enums mapping


    【解决方案1】:

    对于第一部分,我将使用 aenum1,它具有 noalias 设置(因此可以存在具有不同名称的重复值):

    from aenum import NoAliasEnum
    
    class Unqiue(NoAliasEnum):
        first = 1
        one = 1
    

    并在使用中:

    >>> Unique.first
    <Unique.first: 1>
    
    >>> Unique.one
    <Unique.one: 1>
    
    >>> # name lookup still works
    >>> Unique['one']
    <Unique.one: 1>
    
    >>> # but value lookups do not
    >>> Unique(1)
    Traceback (most recent call last):
      ...
    TypeError: NoAlias enumerations cannot be looked up by value
    

    对于第二部分,决定你想要的:

    • 从文件中读取和创建枚举
    • 在 Python 中创建枚举并写入文件

    两者都做似乎没有多大意义。

    要从文件创建,您可以使用我的JSONEnumMeta 答案。

    要写入文件,您可以使用我的share enums with arduino 答案(在调整__init_subclass__ 代码之后)。

    我唯一不确定的是语法检查器和自动完成支持的最后一点。


    1 披露:我是Python stdlib Enumenum34 backportAdvanced Enumeration (aenum) 库的作者。

    【讨论】:

    • 因为它是一个普通的类和Members默认的类成员,大多数编码工具应该支持这个开箱即用
    • 感谢@EthanFurman 的回答。不幸的是,通过这种方法,我必须使用Unique.first.value 来访问我根本不喜欢的实际值。所以现在我决定简单地使用一个带有模块范围变量的模块,可以使用模块上的内置 vars() 进行迭代,并跳过任何以下划线开头和结尾的内容。我知道这可能被视为滥用,但在我所知道的所有解决方案中,这是我最喜欢的一个(至少在我遇到新困难之前)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多