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

Imagine a class that works like a container of database table information (table names and columns).

This is an implementation.

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"

My goal would be to access the value of the enum (which are the classes TABLE1 or TABLE2) without explicitly calling the value attributes.

So if for example I want to concatenate the first two columns of the first table I want to write

TABLES.TABLE1.COL1 + TABLES.TABLE1.COL2

instead of

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

I don't need the class TABLES to be an enum, but I have two requirements:

  • TABLES needs to be iterable
  • I'd like to see the whole choice of tables once I write TABLES.

Moreover, I need single tables to be classes because I want to add a small documentation on each of them.



Solution 1:[1]

If all you need is your class to be iterable, you can use a use a metaclass. Register your nested class to participate in the iteration by inheriting from .Value

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])

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1