我可以避免使用 "value" 属性来实际检索枚举中元素的值吗?

Can I avoid to use the "value" attribute to actually retrieve the value of an element in an Enum?

想象一个 class 像数据库 table 信息(table 名称和列)的容器一样工作。

这是一个实现。

class TABLES(Enum):

    class TABLE1: 
        """ documentation for first table """
        NAME = "My First Table"
        COL11 = "col11"
        COL12 = "col12"
        COL13 = "col13"

    class TABLE2: 
        """ documentation for second table """
        NAME = "My Second table"
        COL21 = "col21"
        COL22 = "col22"
        COL23 = "col23"

我的目标是在不显式调用 value 属性的情况下访问枚举的值(即 classes TABLE1TABLE2)。

所以如果我想连接第一列的前两列 table 我想写

TABLES.TABLE1.COL1 + TABLES.TABLE1.COL2

而不是

TABLES.TABLE1.value.COL1 + TABLES.TABLE1.value.COL2

我不需要 class TABLES 作为枚举,但我有两个要求:

此外,我需要单个 table 为 class,因为我想为每个添加一个小文档。

您可以对外部 Tables class 使用 namedtuple,对实际 table 定义使用普通 class:

from collections import namedtuple

class Table: pass

class Table1(Table): 
    """ documentation for first table """
    NAME = "My First Table"
    COL11 = "col11"
    COL12 = "col12"
    COL13 = "col13"

class Table2(Table): 
    """ documentation for second table """
    NAME = "My Second table"
    COL21 = "col21"
    COL22 = "col22"
    COL23 = "col23"

Tables = namedtuple("Tables", (t.__name__ for t in Table.__subclasses__()))
TABLES = Tables(*Table.__subclasses__())

这允许写入 TABLES.Table1.COL11 并且还允许遍历 TABLES
继承和 __subclasses__ 仅用于将 table class 自动添加到命名元组中。

一个不同的解决方案是在您自己的代码中添加一个方法,列出 tables:

class Tables:
    class Table1: 
        """ documentation for first table """
        NAME = "My First Table"
        COL11 = "col11"
        COL12 = "col12"
        COL13 = "col13"

    class Table2: 
        """ documentation for second table """
        NAME = "My Second table"
        COL21 = "col21"
        COL22 = "col22"
        COL23 = "col23"

    def list_tables():
        return (var for name, var in vars(Tables).items()
                if not name.startswith("__") and type(var) == type)

这也应该允许写入 Tables. 以获得 table 的列表(尽管这取决于您的 IDE 的功能)。

如果您只需要 class 可迭代,您可以使用 metaclass。通过从 .Value

继承来注册您的嵌套 class 以参与迭代
class BagOfClass(type):
    class Value:
        pass

    def __iter__(klass):
        for attr_value in vars(klass).values():
            if isinstance(attr_value, type) and issubclass(
                attr_value, BagOfClass.Value
            ):
                yield attr_value


class Tables(metaclass=BagOfClass):
    class Table1(BagOfClass.Value):
        """documentation for first table"""

        NAME: str = "My First Table"
        COL11: str = "col11"
        COL12: str = "col12"
        COL13: str = "col13"

    class Table2(BagOfClass.Value):
        """documentation for second table"""

        NAME: str = "My Second table"
        COL21: str = "col21"
        COL22: str = "col22"
        COL23: str = "col23"


print(*[table.NAME for table in Tables])