Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/297.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 使用自动值的简洁语法创建StringAutoEnum类_Python_Python 3.x_Enums - Fatal编程技术网

Python 使用自动值的简洁语法创建StringAutoEnum类

Python 使用自动值的简洁语法创建StringAutoEnum类,python,python-3.x,enums,Python,Python 3.x,Enums,我正在尝试实现一个StringAutoEnum类,它可以将其成员值设置为成员名称的小写版本,而不必为每个值调用auto(),因为这太冗长了,我不喜欢它 假设此基本StringAutoEnum类: import aenum class StringAutoEnum(aenum.Enum): def _generate_next_value_(name, start, count, last_values): return name.lower() 理想情况如下: cla

我正在尝试实现一个StringAutoEnum类,它可以将其成员值设置为成员名称的小写版本,而不必为每个值调用auto(),因为这太冗长了,我不喜欢它

假设此基本
StringAutoEnum
类:

import aenum

class StringAutoEnum(aenum.Enum):
    def _generate_next_value_(name, start, count, last_values):
        return name.lower()
理想情况如下:

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE
以确保以下情况属实:

Animal.DOG.value == "dog"
Animal.CAT.value == "cat"
Animal.SNAKE.value == "snake"
显然,上面的类定义甚至不是有效的python代码(除非已经预先定义了DOG、CAT和SNAKE),所以这样做(据我所知)是不可能的

因此,我考虑的几个备选方案如下:

分配给多个变量:

class Animal(StringAutoEnum):
    DOG = CAT = SNAKE = auto()
可拆箱:

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE = auto()
重申一下,我不想这样做:

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE = auto(), auto(), auto()
我也不想使用函数式API

分配给多个变量的问题似乎是,auto()对于第一个变量名只计算一次,因此枚举的所有3个成员都以名称“DOG”和值“DOG”结束。我还没有找到解决这个问题的办法

iterable解包的问题是,我想不出任何方法来提前知道赋值运算符左侧有多少个变量

这意味着,虽然这将起作用,并将完全满足我的要求:

class Auto(aenum.auto):
    def __iter__(self):
        return iter([Auto() for _ in range(3)])

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE = Auto()
不幸的是,这不会:

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE, EMU = Auto()
我想不出任何办法来解决这个问题,分配给任意数量的成员

有没有人能想出一种简洁明了的方法来解决这个问题?或者,有人能提出一个可行的多变量赋值实现方案吗

提前谢谢

既然您正在使用,您就可以选择
AutoEnum
——它充分体现了元类的魔力:

from aenum import AutoEnum

class StringAutoEnum(AutoEnum):
    #
    def _generate_next_value_(name, start, count, last_values):
        return name.lower()

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE

--> list(Animal)
[<Color.Dog: 'dog'>, <Color.CAT: 'cat'>, <Color.SNAKE: 'snake'>]
从aenum导入自动枚举
类StringAutoEnum(自动枚举):
#
定义生成下一个值(名称、开始、计数、最后一个值):
返回name.lower()
动物类(StringAutoEnum):
狗、猫、蛇
-->名单(动物)
[, ]

如果这太神奇了,下一个最好的解决方案是对每个值使用
auto()
(或使用函数API)。

这可以通过标准库轻松实现:

从枚举导入枚举
类StringAutoEnum(str,Enum):
@静力学方法
定义生成下一个值(名称*):
返回name.lower()
Animal=StringAutoEnum('Animal'、'DOG-CAT-SNAKE')
列表(动物) [, ] 新类的第二个参数也可以是iterable而不是string


使用
str
mixin类型不是必需的,但允许您直接将枚举值(在本例中为小写名称)作为字符串使用,而无需先强制转换它们

哇。我真不敢相信我竟然不知道AutoEnum类。它基本上是完美的!您所描述的方法的唯一缺点是linters不喜欢它,因此您必须#noqa这一行。我在问题中提到,我不想使用函数API。原因是代码内省引擎和IDE通常无法理解以这种方式声明的枚举,因此您最终会失去通过使用类语法声明枚举而获得的自动完成和linting功能,这是使用枚举而不仅仅是“魔术字符串”的一半原因。
>>> list(Animal)
[<Animal.DOG: 'dog'>, <Animal.CAT: 'cat'>, <Animal.SNAKE: 'snake'>]