Home > Software engineering >  How to add a list of field names to a class based on NamedTuple?
How to add a list of field names to a class based on NamedTuple?

Time:09-02

I have a basic class like this:

from typing import NamedTuple

class A(NamedTuple):
    f1: str = ""


aa = A("haha")
print(aa)

Now suppose I have a list of more fields that I want to use in Class A, essentially:

more_field_names = ['f2', 'f3', 'f4']

and I want to make Class A look like this, but without manually typing all the field names:

class A(NamedTuple):
    f1: str = ""
    f2: str = ""
    f3: str = ""
    f4: str = ""

Is there a way to use something like list comprehension to add each field names to the Class A definition?

CodePudding user response:

I'm not entirely sure if this is what you're looking for, but you can dynamically generate the class definition to copy-paste into a python file, based on a list of fields that you want to add (assuming you have a lot of same-type fields to add):

def gen_named_tuple_schema(fields: list[str], class_name='A'):
    fields = '\n'.join(f"    {f}: str = ''" for f in fields)
    return f'class {class_name}(NamedTuple):\n{fields}'

Then you can use it like so:

print(gen_named_tuple_schema(['f1', 'f2', 'f3', 'f4']))

Output:

class A(NamedTuple):
    f1: str = ''
    f2: str = ''
    f3: str = ''
    f4: str = ''

CodePudding user response:

from typing import NamedTuple
fields = {f'f{i}': str for i in range(5)}
foo = NamedTuple('foo', **fields)
print(foo.__annotations__)
# {'f0': str, 'f1': str, 'f2': str, 'f3': str, 'f4': str}

CodePudding user response:

Consider using the namedtuple() factory function from the collections module. As shown in the documentation, it is well suited to supplying the field names as data:

from collections import namedtuple

A = namedtuple('A', ('f1'))
B = namedtuple('B', A._fields   ('f2', 'f3', 'f4'))

Optionally default values can given as well:

Person = namedtuple('Person', ('name', 'age', 'points'), defaults=(0, 0))

Annotations can be added dynamically using the same technique as in the code for NamedTuple:

types = {'name': str, 'age': int, 'points': int}
Person.__annotations__ = Person.__new__.__annotations__ = types

Dynamically added types will show-up in tool tips, help(), and calls to inspect.get_signature(). Static type checkers such as MyPy may have trouble with dynamically generated information.

  • Related