【问题标题】:Is it possible to call the constructor of a class that inherits Enum without arguments?是否可以调用不带参数继承 Enum 的类的构造函数?
【发布时间】:2019-04-25 14:24:17
【问题描述】:

我有多个类,有些继承 Enum,有些不继承,所有这些最终都混合在大数组中,如下所示:

from enum import Enum

class TestEnum(Enum):
    VAL_A = 0
    VAL_B = 1

class TestNotEnum():
    def __init__(self):
        self.var = 1

由于我希望有一个尽可能简单的代码供其他人使用,我想以相同的方式调用所有类的构造函数,以避免尽可能多的混乱。

这就是我想要初始化它们的方式:

classes = [TestEnum(), TestNotEnum()]

TestNotEnum 类没有问题,但TestEnum 抛出以下异常:TypeError: __call__() missing 1 required positional argument: 'value'。这是由于我(错误地)使用了 Enum。

我该怎么做才能让TestEnum 类仍然继承 Enum 并且有一个没有参数的构造函数?

我尝试了以下(以及一些类似的调整):

class TestEnum(Enum):
    VAL_A = 0
    VAL_B = 1
    def __init__(self):
        super(TestEnum, self).__init__()

但我最终只会遇到不同的错误,例如TypeError: __init__() takes 1 positional argument but 2 were given

【问题讨论】:

  • classes 列表的具体用途是什么?你打算如何使用它的成员?文档中的 Planet 示例向您展示了如何在 Enum 子类上定义 __init__(),但我不确定您想要它做什么。
  • 在我使用的 API 中,这些类封装了与另一台机器通信的位(0 和 1)。类数组内容的顺序允许程序知道如何解释这些位。这也允许在协议更改时轻松调整程序(因为用户只需交换类的顺序/添加一个/删除一个)
  • 好吧,这听起来有点过头了,但documentation 似乎表明 Enum 子类被设计为永远不会被显式实例化。
  • 啊,你是对的,你的链接给出了答案:这是不可能的,因为枚举都是单例。谢谢你的回答^^。

标签: python class enums constructor python-3.4


【解决方案1】:

你有一个选择是让工厂函数像你的枚举一样命名:

from enum import Enum

class TestEnum(Enum):
    VAL_A = 0
    VAL_B = 1

def TestEnum1():
    return TestEnum

class TestNotEnum():
    def __init__(self):
        self.var = 1


instances = [TestEnum1(), TestNotEnum()]
print(instances)

输出:

[<enum 'TestEnum'>, <__main__.TestNotEnum object at 0x03648E30>]

【讨论】:

  • 这是一个优雅的解决方案 - 谢谢 - 但我仍然需要解释某些类不能直接调用的文档。如果没有更好的发现我会使用它
  • 嗯,枚举是单例(感谢@glibdud 提供的信息),因此,我无法按我的意愿实例化该类
【解决方案2】:

鉴于这对于 python 的内置 enum 类是不可能的,一个潜在的解决方法是使用高级 enum 包。只需将from enum import Enum 替换为from aenum import enum as Enum,您现有的代码就可以正常工作。

from aenum import enum as Enum
class TestEnum(Enum):
    VAL_A = 0
    VAL_B = 1
    def __init__(self):
        super(TestEnum, self).__init__()
class TestNotEnum():
    def __init__(self):
        self.var = 1
classes = [TestEnum(), TestNotEnum()]

【讨论】:

  • 请注意,我使用了from aenum import enum as Enum,因为您当前的代码已经使用大写 E 表示枚举 - 如果您只想使用 from aenum import enum,并相应地更改其余代码中的大小写,你不需要那个部分。
  • 我看到了,谢谢。是否可以遍历属性?
  • 小写的enum不是Enum类型——不能是list()ed,缺少改进的repr(),无法正常交互实际Enum's。
【解决方案3】:

感谢@glibdud 对我的问题发表评论=> 不可能像here 那样显示:所有枚举类都是单例,因此我不能按照我希望的方式调用构造。

其他给定的解决方案很有趣,但不符合我的需求(aenum 增加了新的约束,工厂函数为 API 用户增加了一层新的复杂性)

另一种可能性是创建自己的 Enum 类以满足我的需求,但我选择重做我的架构,因为它更快:我没有以这种方式放置类实例 classes = [TestEnum(), TestNotEnum()],而是放置了引用 classes = [TestEnum, TestNotEnum]作为模板数组,希望的值在第二个相同大小的数组中。

没有我想要的解决方案那么好,但它可以工作并且允许 API 用户做最少的工作,因为他不编辑模板数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-23
    • 2013-01-24
    • 1970-01-01
    • 2015-06-16
    • 2011-01-02
    • 2013-02-12
    • 2018-03-31
    • 1970-01-01
    相关资源
    最近更新 更多