使用自定义混合类型创建枚举

发布于 2025-02-08 13:28:17 字数 2922 浏览 1 评论 0原文

文档,提到混合类型可用于确保项目属于该类型并充当该类型的对象,例如:

class IntEnum(int, Enum):
    pass

但是,该文档没有在上提供任何示例自定义类作为混合类型,我对此失败了。有可能吗?如果是这样,我该怎么做?


我要编写的代码是

@dataclass
class Field:
    dtype: str
    name: str

@dataclass
class FwfField(Field):
    width: int

    def __post_init__(self):
        if self.width <= 0:
            raise ValueError("Field width must be positive.")

class CnefeSchema(FwfField, Enum):
    state_code = ("int", "Código da UF", 2)
    ...

从另一个文件导入cnefeschema时,我

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [1], in <cell line: 1>()
----> 1 from src.conf.schemas import CnefeSchema

File src/conf/schemas.py:25, in <module>
     21     pass
     24 # TODO automatically read schema from Layout
---> 25 class CnefeSchema(EnumFwfField, Enum):
     27     @classmethod
     28     def parse(cls) -> tuple[list, dict, dict]:
     29         """
     30         Get field widths, dtypes, and columns from schema.
     31
   (...)
     34         as `pandas.read_fwf`.
     35         """

File /usr/lib/python3.10/enum.py:298, in EnumMeta.__new__(metacls, cls, bases, classdict, **kwds)
    296 enum_member._name_ = member_name
    297 enum_member.__objclass__ = enum_class
--> 298 enum_member.__init__(*args)
    299 # If another member with the same value was already defined, the
    300 # new member becomes an alias to the existing one.
    301 for name, canonical_member in enum_class._member_map_.items():

File <string>:4, in __init__(self, dtype, name, width)

File /usr/lib/python3.10/types.py:187, in DynamicClassAttribute.__set__(self, instance, value)
    185 def __set__(self, instance, value):
    186     if self.fset is None:
--> 187         raise AttributeError("can't set attribute")
    188     self.fset(instance, value)

AttributeError: can't set attribute

已经尝试过:

  • 定义另一个类,enumfwffield,并使用它作为混合,即 在 经过 类Cnefeschema(Enumfwfffield,Enum): ... 但是我得到的错误与上面相同;
  • enum fields设置(在此示例中,state_code)为fwffield,即
     类Cnefeschema(fwffield,Enum)
        state_code = fwffield(“ int”,“códigoda uf”,2)
        ...
     
    但是我得到了 < 文件“ src/conf/schemas.py”,第25行,in&lt; module&gt; 类Cnefeschema(Enumfwfffield,Enum): 文件“/usr/lib/python3.10/enum.py”,第298行,in __new__ enum_member .__ init __(*args) typeError:fwffield .__ INT __()缺少2个必需的位置参数:'name'和'width'

In the relevant section of the Python Enum documentation, it is mentioned that mix-in types can be used to ensure items belong to that type and act as objects of that type, like in the example:

class IntEnum(int, Enum):
    pass

However, the documentation does not give any examples on how to use a custom class as a mix-in type, and I've failed miserably at that. Is it even possible? And if so, how do I do it?


The code I'm trying to write is

@dataclass
class Field:
    dtype: str
    name: str

@dataclass
class FwfField(Field):
    width: int

    def __post_init__(self):
        if self.width <= 0:
            raise ValueError("Field width must be positive.")

class CnefeSchema(FwfField, Enum):
    state_code = ("int", "Código da UF", 2)
    ...

When I import CnefeSchema from another file or run it, I get

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [1], in <cell line: 1>()
----> 1 from src.conf.schemas import CnefeSchema

File src/conf/schemas.py:25, in <module>
     21     pass
     24 # TODO automatically read schema from Layout
---> 25 class CnefeSchema(EnumFwfField, Enum):
     27     @classmethod
     28     def parse(cls) -> tuple[list, dict, dict]:
     29         """
     30         Get field widths, dtypes, and columns from schema.
     31
   (...)
     34         as `pandas.read_fwf`.
     35         """

File /usr/lib/python3.10/enum.py:298, in EnumMeta.__new__(metacls, cls, bases, classdict, **kwds)
    296 enum_member._name_ = member_name
    297 enum_member.__objclass__ = enum_class
--> 298 enum_member.__init__(*args)
    299 # If another member with the same value was already defined, the
    300 # new member becomes an alias to the existing one.
    301 for name, canonical_member in enum_class._member_map_.items():

File <string>:4, in __init__(self, dtype, name, width)

File /usr/lib/python3.10/types.py:187, in DynamicClassAttribute.__set__(self, instance, value)
    185 def __set__(self, instance, value):
    186     if self.fset is None:
--> 187         raise AttributeError("can't set attribute")
    188     self.fset(instance, value)

AttributeError: can't set attribute

I've already tried:

  • Defining another class, EnumFwfField, and using it as a mix-in, i.e.
    class EnumFwfField(FwfField, Enum):
        pass
    
    class CnefeSchema(EnumFwfField, Enum):
        ...
    

    but I get the same error as above;

  • Setting the Enum fields (in this example, state_code) to FwfField, i.e.
    class CnefeSchema(FwfField, Enum):
        state_code = FwfField("int", "Código da UF", 2)
        ...
    

    but then I get

    Traceback (most recent call last):
      File "src/conf/schemas.py", line 25, in <module>
        class CnefeSchema(EnumFwfField, Enum):
      File "/usr/lib/python3.10/enum.py", line 298, in __new__
        enum_member.__init__(*args)
    TypeError: FwfField.__init__() missing 2 required positional arguments: 'name' and 'width'
    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

听风念你 2025-02-15 13:28:17

您存在的问题是因为在上面的代码中,您在name属性 field dataclass中具有名称属性。

将该字段重命名为其他东西,例如'dname',它应该起作用。

(3.11中的错误消息更具信息性。)

The issue you are having is because in your above code you have a name attribute in your Field dataclass, but Enum will not let you set a name attribute.

Rename that field to something else, for example 'dname', and it should work.

(The error message in 3.11 is more informative.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文