Python 派生枚举缺少必需的位置参数

Python derived enum missing required positional argument

我正在尝试定义一个对象值枚举,但我 运行 在 enum_member.__init__(*args)

中出现“缺少 1 个必需的位置参数”错误

我的代码的一个基本示例,在 the documentation from enum 之后,我们称它为 problem.py,它是在 upper.py

中导入的
import enum

class test(object):
   def __init__(self, par1, par2):
      # do stuff with the parameters and assign to object fields

   # more object methods

class testlist(test, enum.Enum):
   A = test(1,2)
   B = test(3,4),
   # a few more of these

导入定义了这些 类 的模块时,出现以下错误(已编辑以匹配示例):

 File "upper.py", line 14, in <module>
    from problem import test
  File "problem.py", line 75, in <module>
    class testlist(test, enum.Enum):
  File "/usr/lib/python3.8/enum.py", line 252, in __new__
    enum_member.__init__(*args)
TypeError: __init__() missing 1 required positional argument: 'par2'

我猜我误解了派生枚举的工作原理,但从文档中我无法弄清楚我是如何遗漏一个参数的。

(编辑) 目标是让 testlist 值表现为 test 对象,它还定义了一些方法并覆盖了算术运算符,所以我可以做到,例如 testlist.A + testlist.B。枚举不是绝对必要的,但它便于迭代,并且比将它们作为模块中的全局变量更好地对值进行分组。

请注意枚举对于 __new____init__ 有自己的方式,在您的情况下,您不需要将 test 作为 parent class.如果您确实需要,请按照文档 https://docs.python.org/3/library/enum.html#when-to-use-new-vs-init

没有 test class 作为你的 parent class,它会工作

import enum

class test:
    def __init__(self, par1, par2):
        print(self, par1, par2)

class testlist(enum.Enum):
    A = test(1, 2)
    B = test(3, 4)

编辑:下面的代码支持 + 运算符 检查输出以了解更多 enum subclassing 是如何工作的。

import enum

class test(object):
    def __init__(self, par1, par2):
        print(self,':', par1, par2)
        self.par1 = par1
        self.par2 = par2

    def __add__(self, rval):
        print("test:", self, "+", rval)

class testlist(test, enum.Enum):
    A = (1,2)
    B = (3,4)
    # a few more of these
    def __new__(cls, par1, par2):
        obj = object.__new__(cls)
        obj._value_ = test(par1, par2)
        return obj
    def __init__(self, *args):
        print(self.__class__, args)


# call __add__ of `testlist` if exist, otherwise __add__ of `test`
testlist.A + testlist.B
# value is `test` object
testlist.A.value + testlist.B.value

输出

<__main__.test object at 0x7f112f1d7430> : 1 2
<enum 'testlist'> (1, 2)
<__main__.test object at 0x7f112f1f52e0> : 3 4
<enum 'testlist'> (3, 4)
test: testlist.A + testlist.B
test: <__main__.test object at 0x7f112f1d7430> + <__main__.test object at 0x7f112f1f52e0>

旁白:在您的 B = test(3,4), 示例中,最后的逗号不应该出现。


你 运行 的意思是,当你对另一个数据类型进行子类化时,无论你分配给成员名称的是什么,都将传递给子类化类型的 __new__ and/or __init__.

换句话说,通过从 test 继承,您的 testlist 枚举现在有一个 __init__,它需要两个参数:一个用于 par1,一个用于 par2——但你只提供了一个参数,例如test(1, 2)。您需要提供的只是 1, 2:

class testlist(test, enum.Enum):
    A = 1, 2
    B = 3, 4
    # a few more of these

在上面的代码中,A 的值将通过调用 test(1, 2).

来计算

另一个可能有帮助的示例:可以使用两个参数调用 int,第一个是 str,第二个是解释该字符串的基数。所以:

class Count(IntEnum):
    ONE = 1              # value generated by int(1)
    TWO = '2'            # value generated by int('2')
    THREE = '3', 10      # value generated by int('3', 10)
    TEN = 'A', 16        # value generated by int('A', 16)

list编辑时:

>>> list(Count)
[<Count.ONE: 1>, <Count.TWO: 2>, <Count.THREE: 3>, <Count.TEN: 10>]