pythonenumsname-value

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:

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


Solution

  • You can use a namedtuple for the outer Tables class and normal classes for the actual table definitions:

    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__())
    

    This allows writing TABLES.Table1.COL11 and also allows iterating over TABLES.
    Inheritance and __subclasses__ is only used to add the table classes automatically to the namedtuple.

    A different solution is to just add a method to your own code, that lists the 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)
    

    This should also allow writing Tables. to get a list of tables (although this depends on the features of your IDE).