Search code examples
pythonpython-3.xnamedtuplepython-dataclassespython-attrs

Can you use namedtuples/dataclass/attrs to create a flexible sized class or do you have to use traditional classes?


If there is a json data set that looks like this.

[
{'a':1,'b':'fire','c':'cambodia','type':'charizard'},
{'a':2,'d':'waterparks','type':'squirtle'},
{'a':3,'f':'thunder','type':'pikachu'}
]

And it is needed to transition it into a set of objects where the objects can be defined with the same class like this.

charizard = Pokemon(row_data)
pickachu = Pokemon(row_data)
squirtle = Pokemon(row_data)

But the attributes are accessible via dot notation, like this.

charizard.a
pikachu.d
squirtle.a

The way to do that with traditional classes is like this.

class Pokemon(object):
    def __init__(self, data):
        for k, v in data.items():
            setattr(self, k, v)

Is there a way to do basically the same thing with either namedtuples or dataclasses or attrs that works for data of different sizes and has all the nice immutability, repr, etc. functionality of those data types.


Solution

  • The point of attrs et al is to have well-defined classes for your data. So the short answer to your question is “no”.

    Setting attributes dynamically like you you want to doesn’t buy you much, except that it’s less typing to access your data.

    A better way is to have well-defined classes where one look tells you what attributes to expect and serialize/normalize your JSON into it. There’s a bunch of packages for that; for attrs there’s cattrs for instance. Or you just write a function or class method.

    The time you spend making this transition explicit, you’ll get back tenfold when debugging later.