首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python Lazy Enum

Python Lazy Enum
EN

Stack Overflow用户
提问于 2021-02-08 19:33:13
回答 1查看 429关注 0票数 3

我正在尝试创建一个带有惰性评估的enum.Enum

根据医生的说法:

枚举是一组符号名(成员),绑定到唯一的常量值。在枚举中,成员可以通过标识进行比较,枚举本身也可以迭代。

我想说,我的案件仍然属于这个定义的范围。这些值仍然是唯一和不变的,我只希望它们在必要时被初始化。这可能是因为初始化很耗时,依赖于其他Enum成员,与其他Enum具有循环依赖关系,或者(在我当前的例子中)是因为初始化需要一个运行的QGuiApplication,如果一个模块没有运行(当然还有其他方法来绕过这个特定的需求,那么我希望模块仍然是不可输入的(但保持特定的枚举不可用)。

we are only supposed to subclass EnumMeta in rare cases开始,我想通过子类Enum本身来实现这一点:

代码语言:javascript
运行
复制
class Lazy:
    def __init__(self, value):
        self.value = value

class LazyEnum(Enum):
    def __getattribute__(self, name):
        result = super().__getattribute__(name)
        if name == 'value' and isinstance(result, Lazy):
            result = self._lazy_init(result.value)
            self.__setattr__(name, result)
        return result

这样做的目的是将一些值标记为Lazy,以便稍后初始化。但是,我的示例代码:

代码语言:javascript
运行
复制
class MyEnum(LazyEnum):
    X = Lazy('x')
    Y = Lazy('y')
    Z = 'z'

    def _lazy_init(self, value):
        print(f"Evaluating {value}")
        return value * 2

print(MyEnum.X.value)
print(MyEnum.X)
print(MyEnum.X.value)

引发错误:

代码语言:javascript
运行
复制
AttributeError: can't set attribute

我该怎么解决这个问题?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-11 12:56:33

我查看了Enum的源代码,并通过直接设置_value_属性而不是value属性来解决这个问题。这个解决方案让我觉得有些烦躁,但它似乎奏效了:

代码语言:javascript
运行
复制
from abc import ABCMeta, abstractmethod
from enum import Enum, EnumMeta


class AbstractEnumMeta(EnumMeta, ABCMeta):
    pass


class Lazy:
    def __init__(self, *lazy_init_arguments):
        self.args = lazy_init_arguments


class LazyEnum(Enum, metaclass=AbstractEnumMeta):
    def __getattribute__(self, name):
        result = super().__getattribute__(name)
        if name == 'value' and isinstance(result, Lazy):
            result = self._lazy_init(*result.args)
            setattr(self, '_value_', result)
        return result

    @classmethod
    @abstractmethod
    def _lazy_init(cls, *args):
        return args


class MyEnum(LazyEnum):
    X = Lazy('x')
    Y = Lazy('y')
    Z = 'z'

    @classmethod
    def _lazy_init(cls, value):
        print(f"Lazy init of {value}")
        return value * 2


>>> MyEnum.Z
MyEnum.Z
>>> MyEnum.Z.value
'z'
>>> MyEnum.X
MyEnum.X
>>> MyEnum.X.value
Lazy init of x
'xx'
>>> MyEnum.X.value
'xx'
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66108148

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档