Keeping a list of records with named fields that can be updated

Peter Otten __peter__ at web.de
Mon Dec 19 13:29:20 EST 2022


On 18/12/2022 16:44, songbird wrote:
> Peter Otten wrote:
> ...
>> While I think what you need is a database instead of the collection of
>> csv files the way to alter namedtuples is to create  a new one:
>>
>>>>> from collections import namedtuple
>>>>> Row = namedtuple("Row", "foo bar baz")
>>>>> row = Row(1, 2, 3)
>>>>> row._replace(bar=42)
>> Row(foo=1, bar=42, baz=3)
>
>    namedtuple is easier to use as that will use the csv and
> csvreader and create the records without me having to do any
> conversion or direct handling myself.  it's all automagically
> done.  my initial version works, but i'd like it to be a bit
> more elegant and handle descriptions it hasn't seen before
> in a more robust manner.
>
>
>> An alternative would be dataclasses where basic usage is just as easy:
>>
>>>>> from dataclasses import make_dataclass
>>>>> Row = make_dataclass("Row", "foo bar baz".split())
>>>>> row = Row(1, 2, 3)
>>>>> row
>> Row(foo=1, bar=2, baz=3)
>>>>> row.bar = 42
>>>>> row
>> Row(foo=1, bar=42, baz=3)
>
>    i do like that i can directly reference each field in a
> dataclass and not have to specify a _replace for each change.
>
>    is there an easy way to convert from namedtuple to dataclass?
> i can see there is a _asdict converter, but don't really like
> how that turns out as then i have to do a bunch of:
>      rec['fieldname'] = blah
>
> rec.fieldname is much easier to understand.

I recommend that you use a dataclass /instead/ of a namedtuple, not
both. However, for a dataclass with the same fields in the same order as
in your namedtuple the conversion is trivial:

Create compatible namedtuple and dataclass types:

 >>> NTRow = namedtuple("NTRow", ["alpha", "beta", "gamma"])
 >>> DCRow = make_dataclass("DCRow", NTRow._fields)

Build the namedtuple:

 >>> ntrow = NTRow(1, "two", 3.0)
 >>> ntrow
NTRow(alpha=1, beta='two', gamma=3.0)

Convert to dataclass:

 >>> dcrow = DCRow(*ntrow)
 >>> dcrow
DCRow(alpha=1, beta='two', gamma=3.0)



More information about the Python-list mailing list