Using namedtuples field names for column indices in a list of lists

Steven D'Aprano steve+comp.lang.python at
Sun Jan 8 22:29:51 EST 2017

On Sunday 08 January 2017 20:53, Deborah Swanson wrote:

> Steven D'Aprano wrote, on January 07, 2017 10:43 PM
>> On Sunday 08 January 2017 16:39, Deborah Swanson wrote:
>> > What I've done so far:
>> > 
>> > with open('E:\\Coding projects\\Pycharm\\Moving\\Moving
>> 2017 in.csv',
>> > 'r') as infile:
>> >     ls = list(csv.reader(infile))
>> >     lst = namedtuple('lst', ls[0])
>> > 
>> > where 'ls[0]' is the header row of the csv, and it works perfectly
>> > well. 'lst' is a namedtuple instance with each of the
>> column titles as
>> > field names.
>> Are you sure? namedtuple() returns a class, not a list:
> Yes. 'ls' is defined as 'list(csv.reader(infile))', so ls[0] is the
> first row from the csv, the header row. 'lst' is the namedtuple.
> Perhaps what's puzzling you is that the way I've written it, the list of
> data and the namedtuple are disjoint, and that's the problem.

No, I'm pretty sure that's not the case. I don't have access to your CSV file, 
but I can simulate it:

ls = [['Location', 'Date', 'Price'],
      ['here', '1/1/17', '1234'],
      ['there', '1/1/17', '5678'],
      ['everywhere', '1/1/17', '9821']

from collections import namedtuple
lst = namedtuple('lst', ls[0])


If you run that code, you should see:

<class 'type'>
<class '__main__.lst'>

which contradicts your statement:

    'lst' is a namedtuple instance with each of the column 
    titles as field names.

and explains why you had to access the individual property method `fget`: you 
were accessing the *class object* rather than an actual named tuple instance.

The code you gave was:


where l was not given, but I can guess it was a row of the CSV file, i.e. an 
individual record. So:

- lst was the named tuple class, a subclass of tuple

- lst.Location returns a property object

- lst.Location.fget is the internal fget method of the property object.

I think Peter Otten has the right idea: create a list of records with something 
like this:

Record = namedtuple('Record', ls[0])
data = [Record(*row) for row in ls[1:])

or if you prefer Peter's version:

data = [Record._make(row) for row in ls[1:])

Half the battle is coming up with the right data structures :-)

"Ever since I learned about confirmation bias, I've been seeing 
it everywhere." - Jon Ronson

More information about the Python-list mailing list