python - Python 3.5 内部类(枚举)中静态/类列表/字典的初始化

标签 python dictionary enums static inner-classes

是否可以像其他变量一样在内部枚举类中初始化静态/类字典?

# file Outer.py
from enum import Enum
class Outer:
    def callInner(self):
        all_a = Outer.Inner.ALL
        print(all_a) # prints Inner.ALL instead of the list
        all_b = Outer.Inner.ALL[:] # TypeError Inner is not subscriptable

        for e in all_a: #Inner is not iterable
            print(e.to_string())

    class Inner(Enum):
        A = 1
        B = 2
        ALL = [A,B]
        NAMES = {A : "some_name_other_than_enum_a_name",
                 B : "some_name_other_than_enum_b_name"}

        def to_string(self):
             return Outer.Inner.NAMES[self.value]

if __name__ == '__main__':
    o = Outer()
    o.callInner()

Outer是包含所有逻辑的模块。 Inner 类是一个枚举,它包含枚举键值对 A=1B=2 以及所有可能的枚举(或其任何有趣的子集)。这个想法是有一个用于快速引用和迭代/枚举的列表,而 to_string 可以是包含任何逻辑的 arbritray 方法。名称查找只是为了使问题更清晰而进行的简化。

最佳答案

这里的问题不是你有一个内部类,而是内部类是 Enum ;但是,可以将非成员属性作为Enum的一部分。类--参见this question and answer了解详情。

总而言之,您需要创建 ALLNAMES使用某种描述符以避免将它们转换为枚举成员:

# inherit from `object` if using Python 2
class classattribute:   # was called Constant in the linked answer
    def __init__(self, value):
        self.value = value
    def __get__(self, *args):
        return self.value
    def __set__(self, _, value):
        self.value = value
    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, self.value)

然后在你的Inner中:

    ALL = classattribute([A, B])
    NAMES = classattribute({
            A : "some_name_other_than_enum_a_name",
            B : "some_name_other_than_enum_b_name",
            })

这将避免您在 callInner() 中遇到的错误方法,但会在print(e.to_string())处添加一个新的行:

AttributeError: 'int' object has no attribute 'to_string'

这样做的原因是构建 Enum是一个由两部分组成的过程:

  • 收集所有定义:

    { 'A':1, 'B':2, 'ALL':classattribute([A, B]), 'NAMES':classattribute({'A':..., 'B':...}), 'to_string':method(...), }

  • 改变任何不属于 __dunder__ 的东西, _sunder_ ,也不是descriptor进入枚举成员:

    • A -> <Inner.A: 1>
    • B -> <Inner.B: 2>

这意味着当 ALLNAMES正在创建,AB仍然int s,和int没有 to_string方法。解决这个问题的简单方法是在尝试访问这些方法之前检索枚举成员:self.Inner(e).to_string() .

将所有内容整合在一起,您的代码应如下所示:

# file Outer.py

from enum import Enum

class classattribute:
    def __init__(self, value):
        self.value = value
    def __get__(self, *args):
        return self.value
    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, self.value)

class Outer:
    def callInner(self):
        all_a = Outer.Inner.ALL
        print(all_a)
        all_b = Outer.Inner.ALL[:]
        for e in all_a: #Inner is not iterable
            print(self.Inner(e).to_string())

    class Inner(Enum):
        A = 1
        B = 2
        ALL = classattribute([A,B])
        NAMES = classattribute(
                {A : "some_name_other_than_enum_a_name",
                 B : "some_name_other_than_enum_b_name"}
                )
        def to_string(self):
             return Outer.Inner.NAMES[self.value]

if __name__ == '__main__':
    o = Outer()
    o.callInner()

运行时,您将得到以下结果:

[1, 2]
some_name_other_than_enum_a_name
some_name_other_than_enum_b_name

关于python - Python 3.5 内部类(枚举)中静态/类列表/字典的初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34465739/

相关文章:

c++ - 访问 vector 字段的键 - 命名空间中的枚举类或枚举?

Python - 如何在获取数据的同时避免 Pandas 中的错误(异常)?

java - 通过添加/减去相应的值来合并 map

python - 比较 Swift 和 Python 字典对象

Java从同一对象的不同HashMap中获取最终计算结果

c - 如何检查数据类型是否达到最大容量?

java - 在 JSTL 中访问 Map<Enum, Object>

python - 如何在Python异步服务器中获取新接受连接的IP地址和端口?

python - 在不同的目录中创建一个 excel 文件

python - 在单独的子图中显示 displot - Seaborn