枚举从collections.abc.set继承

发布于 2025-02-13 09:56:15 字数 1137 浏览 0 评论 0原文

我想编写一个从collections.abc.set继承的枚举,其唯一目的是实现所需的抽象方法。该文档提出了三种方法,我可以使用选项2让它开始工作:

collect> collections.abc - 抽象的基础类容器

  1. 现有类和内置类可以注册为ABCS的“虚拟子类”

但我认为使用选项中的枚举在API中看起来更好1)作为collections.abc.set在类签名中更明确...所以我尝试了此操作:

import collections
from enum import Enum


class MyClass(collections.abc.Set, Enum):
    AB = {1}
    CD = {1,2}

    def __iter__(self):
        pass

    def __contains__(self, key):
        pass

    def __len__(self):
        pass

抛出了可预期的错误:

 类myclass(collections.abc.set,enum):
 

typeError:元类冲突:派生类的元类必须是其所有基础元素的(非图案)子类

解决方案将如何使用选项1)看起来像? (已经问过几次,即在这个问题中,但不是从collections.abc 类只是为了覆盖类定义中的抽象方法。)

I want to write an Enum that inherits from collections.abc.Set with the sole purpose of implementing the required abstract methods. The documentation suggests 3 ways of doing it and I can get it to work using option 2:

collections.abc — Abstract Base Classes for Containers

  1. Existing classes and built-in classes can be registered as “virtual subclasses” of the ABCs

But I think the Enum would look better in an API using option 1) as having the collections.abc.Set in the class signature is more explicit... So I tried this:

import collections
from enum import Enum


class MyClass(collections.abc.Set, Enum):
    AB = {1}
    CD = {1,2}

    def __iter__(self):
        pass

    def __contains__(self, key):
        pass

    def __len__(self):
        pass

And the expectable error was thrown:

class MyClass(collections.abc.Set, Enum):

TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

How would a solution using option 1) look like? (It's been asked a few times on SO, namely in this question, but not with a minimal canonical example of inheriting from a collections.abc class just to override the abstract methods in the class definition.)

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

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

发布评论

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

评论(1

噩梦成真你也成魔 2025-02-20 09:56:16

实际上,您所说的“ 2”,即,将枚举注册为虚拟子类是您问题的解决方案:将类注册为虚拟子类不会改变其任何行为 - 也不会添加方法或属性:如果查询的实例是超级阶级的实例或相应的“ IssubClass”呼叫,它将返回“ true”。

您拥有的是经典的元类冲突 - 由于两个元素的行为良好且构建为合作使用 - 除非它们在某些部分明显存在冲突,否则您所要做的就是创建一个从两个元中继承的新元素:

In [29]: from collections.abc import Set

In [30]: from enum import Enum, EnumMeta

In [31]: from abc import ABCMeta

In [33]: class CustomMeta(ABCMeta, EnumMeta): pass

In [34]: class MyClass(Set, Enum, metaclass=CustomMeta):
    ...:     AB = {1}
    ...:     CD = {1,2}
    ...:
    ...:     def __iter__(self):
    ...:         return iter(self.value)
    ...:
    ...:     def __contains__(self, key):
    ...:         key in self.value
    ...:
    ...:     def __len__(self):
    ...:         len(self.value)
    ...:

In [35]: list(MyClass.AB)
Out[35]: [1]

In [36]: list(MyClass.CD)
Out[36]: [1, 2]

Actually, what you are calling "2", that is, registering your enum as a virtual subclass is not a solution for your problem at all: registering a class as a virtual subclass does not change any of its behaviors - nor adds methods or attributes: it simply will return "True"when queried if its instances are instances of the superclass, or for the corresponding "issubclass" call.

What you have is a classic metaclass conflict - and since both metaclasses are well behaved and built to be used cooperatively - unless they are explicitly conflicting in some part, all you have to do is create a new metaclass that inherits from both metaclasses:

In [29]: from collections.abc import Set

In [30]: from enum import Enum, EnumMeta

In [31]: from abc import ABCMeta

In [33]: class CustomMeta(ABCMeta, EnumMeta): pass

In [34]: class MyClass(Set, Enum, metaclass=CustomMeta):
    ...:     AB = {1}
    ...:     CD = {1,2}
    ...:
    ...:     def __iter__(self):
    ...:         return iter(self.value)
    ...:
    ...:     def __contains__(self, key):
    ...:         key in self.value
    ...:
    ...:     def __len__(self):
    ...:         len(self.value)
    ...:

In [35]: list(MyClass.AB)
Out[35]: [1]

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