Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用固定键类型(例如枚举类型)实现dict的最佳方法?_Python_Dictionary_Types - Fatal编程技术网

Python 使用固定键类型(例如枚举类型)实现dict的最佳方法?

Python 使用固定键类型(例如枚举类型)实现dict的最佳方法?,python,dictionary,types,Python,Dictionary,Types,设置 我有一个数据对象,它包含许多属性,比如: FaceProperties(眼睛颜色:EyeColorEnum,has_眼镜:bool, 鼻子长度(毫米):浮动,发型(短发) 所有这些都是可选的,因此实例只能定义其中的一个子集 对于软件的每个单一版本,都有一组固定的受支持属性(尝试设置/获取任何其他属性都会导致实现错误) 很可能我需要不时地在未来的版本中添加一个新的 到目前为止发生了什么 原则上,我非常希望在dict中收集它们,这样我就可以用dict做所有美好的事情(使用新键扩展、迭代、

设置

我有一个数据对象,它包含许多属性,比如:

FaceProperties(眼睛颜色:EyeColorEnum,has_眼镜:bool,
鼻子长度(毫米):浮动,发型(短发)
  • 所有这些都是可选的,因此实例只能定义其中的一个子集
  • 对于软件的每个单一版本,都有一组固定的受支持属性(尝试设置/获取任何其他属性都会导致实现错误)
  • 很可能我需要不时地在未来的版本中添加一个新的
到目前为止发生了什么

原则上,我非常希望在
dict
中收集它们,这样我就可以用
dict
做所有美好的事情(使用新键扩展、迭代、按键访问…)。但是,普通的
dict
(和linter)在使用不受支持的键时不会注意到,例如,由于某些打字错误,尤其是使用字符串键时

出于这些考虑,我使用一个具有普通属性的普通类开始了这个项目,并手动实现了所有通用的东西(迭代等)

有更好的选择吗?

我目前正在重构软件,并开始考虑使用固定键类型的映射(我可以使用
SupportedProperties
Enum
)是否能更好地解决我的问题,以及python中是否存在这样的问题

现在,我可以简单地将枚举值用作普通
dict
的键,这可能还不错,但如果有一些专门的
dict
类甚至不接受其他类型的键,那就更好了

是否有一些收藏(最好是内置的)我可以用它?或者我必须从
UserDict
派生我自己的类并自己进行类型检查吗?

怎么样

从枚举导入枚举
从数据类导入数据类,asdict
类EyeColorEnum(枚举):
蓝色=1
红色=2
@数据类()
类FaceProperties:
眼睛颜色:眼睛颜色枚举=无
戴眼镜:布尔=无
机头长度:浮动=无
头发样式:str=无
fp=FaceProperties(eye\u color=EyeColorEnum.BLUE)
打印(fp)
打印(asdict(fp))
输出

FaceProperties(eye_color=<EyeColorEnum.BLUE: 1>, has_glasses=None, nose_length_mm=None, hair_style=None)
{'eye_color': <EyeColorEnum.BLUE: 1>, 'has_glasses': None, 'nose_length_mm': None, 'hair_style': None}
FaceProperties(眼睛颜色=,有眼镜=无,鼻子长度=无,头发样式=无)
{‘眼睛颜色’:,‘戴眼镜’:无,‘鼻子长度’:无,‘发型’:无}

正如其他人在评论中提到的,您只需进行一次检查,以确保密钥位于特定的值集中:

class FixedKeyDict(dict):
    def __init__(self, *args, allowed_keys=(), **kwargs):
        super().__init__(*args, **kwargs)
        self.allowed_keys = allowed_keys

    def __setitem__(self, key, value):
        if key not in self.allowed_keys:
            raise KeyError('Key {} is not allowed'.format(key))
        super().__setitem__(key, value)
现在给它一个允许值的列表:

hair_dict = FixedKeyDict(allowed_keys=('bald', 'wavy', 'straight', 'mohawk'))

这只覆盖了
[]
操作符,但是,您希望像您所说的那样对
UserDict
进行子类化,并覆盖所有其他方法,但您已经明白了。无论如何,您必须自己实现它,标准库中不存在这样的东西。

您自己实现它并不困难<代码>如果不允许使用密钥:引发异常()您的意思是问如何限制dict的密钥?或者有什么替代方法呢?请看倒数第二段:您可以使用键入支持,但通常只会发出警告。但在某种程度上,这是Python固有的:它就是这么灵活。听起来就像是预先检查就可以提供您所需要的一切。当传递的输入不应被接受时,只需通过检查键是否同步来拒绝它。在那之后,每个人都应该知道什么是什么,试图阻止人们射中自己的脚将是一件麻烦事,而不是值得的事。只需对预先传递的dict添加一个检查,就可以了。@norok2 Umh,不。虽然这并不能解决我的所有问题(例如,迭代似乎不是内置的,而且,我目前仍在使用python 3.6),感谢您指出这些问题,显然是相关的。不知道为什么有人否决了这个。Py3.6有一个后台端口。没错,这并不难。但是,您的示例最好将其用作
face\u dict=FixedKeyDict(允许的\u keys=('eye\u color'、'has\u glasses'、'nose\u length\u mm'、'hair\u style'))
,对于发型,枚举做得很好。