0

We know that if we need to define the column names of a table using pytables we can do it by the following way:

class Project(IsDescription):
    alpha = StringCol(20)
    beta  = StringCol(20) 
    gamma = StringCol(20)

where alpha, beta and gamma are the desired column names of the table. But suppose I would like to use a list "ColumnNames_list" which contains the column names as follows: ColumnNames_list[0] = alpha, ColumnNames_list[1] = beta, ColumnNames_list[2] = gamma

Then how should I define the above class "Project"?

I tried with the following:

ColumnNames_list = []
ColumnNames_list[0] = alpha 
ColumnNames_list[1] = beta 
ColumnNames_list[2] = gamma

class Project(IsDescription):
    for i in range (0, 10):
        ColumnNames_list[i] = StringCol(20)  

It's showing the error:

TypeError: Passing an incorrect value to a table column. Expected a Col (or subclass) instance and got: "2". Please make use of the Col(), or descendant, constructor to properly initialize columns.

Zaman
  • 37
  • 8

1 Answers1

1

There are a few options. The first (easiest) is to add the attributes after you create the class:

class Project(IsDescription):
    pass

for name in ColumnNames_List:
    setattr(Project, name, StringCol(20))

There are lots of different takes on this one (e.g. you could do it via a class decorator).

The next option is to use the builtin type to construct the class:

names = {name: StringCol(20) for name in ColumnNames_List}
Project = type('Project', (IsDescription,), names)

The advantage of this approach is that it still works even if some funky metaclass on IsDescription requires that the attributes be set at class construction time1. While we're talking about metaclasses ... you could use a metaclass to do this, but that is almost certainly overkill.

1This is a rare condition but a few popular 3rd party libraries (e.g. sqlalchemy) use metaclasses in this way.

mgilson
  • 300,191
  • 65
  • 633
  • 696