Erik wrote, on January 09, 2017 5:47 PM > As people keep saying, the object you have called 'records' > is a *list* > of namedtuple objects. It is not a namedtuple. > > IIRC, you create it using a list comprehension which creates the > records. A list comprehension always creates a list.
Well no. The list is created with: records.extend(Record._make(row) for row in rows) I'm new to both namedtuples and list comprehensions, so I'm not exactly sure if this statement is a list comprehension. It looks like it could be. In any case I recreated records in IDLE and got >>> type(records) <class 'list'> So it's a class, derived from list? (Not sure what the 'list' means.) 'records' is in fact a class, it has an fget method and data members that I've used. And it behaves like a list sometimes, but many times not. The only reason I've hedged away from advice to treat records as a list for sorting until I tried it for myself, was because of an awful lot of strange behavior I've seen, while trying to do the same things with namedtuples as I routinely do with scalars and lists. This is all new, and until now, unexplored territory for me. And I generally avoid saying I'm sure or outright agreeing with something unless I really do know it. > The sorted() function and the list.sort() method can be used > to sort a > list containing any objects - it's just a case of telling them how to > obtain the key values to compare (which, in the case of > simple attribute > access which the namedtuple objects allow, > "operator.attrgetter()" will > do that). This is why sorting the list works for you. > > You could sort objects of different types - but you might > need to supply > a function instead of operator.attrgetter() which looks at > the type of > each object and returns something that's obtained differently > for each > type (but which the sort function can compare). > > > > > When you say 'Foo = namedtuple("Foo", "spam ham")', you are > creating a > "factory" which is able to generate "Foo" objects for you. > > When you say "x = Foo(1, 2)" you are using the factory to create an > object for you which has its "spam" and "ham" attributes set to the > values 1 and 2 respectively. > > When you say "records = [Foo(x, y) for x, y in some_iterable()]", you > are creating a list of such objects. This is the thing you > are then sorting. > > > > Does that make sense? > > Regards, E. Perfect sense. And now that I've confirmed in code that both sorted() and .sort() behave as hoped for with namedtuples, I couldn't be happier. ;) The only thing I don't think you have 100% correct is your assertion that records is a list. And I'm really not sure now that records.extend(Record._make(row) for row in rows) is a list comprehension. That's the last statement in the creation of 'records', and immediately after that statement executes, the type function says the resulting 'records' is a class, probably derived from list, but it's not a straight up list. 'records' is enough different that you can't assume across the board that namedtuples created this way are equivalent to a list. You do run into problems if you assume it behaves like a list, or even like standard tuples, because it doesn't always. Believe me, when I first started working with namedtuples, I got plenty snarled up debugging code that was written assuming list behavior to know that a namedtuple of namedtuples is not exactly a list. Or even exactly like a list. But that's just a quibble. The important thing in this context is that both .sort() and sorted() treat it like a list and DTRT. And that's very nice. ;) Deborah -- https://mail.python.org/mailman/listinfo/python-list