On 2017-01-10 03:02, Deborah Swanson wrote:
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.
>
This is a list comprehension:

    [Record._make(row) for row in rows]

and this is a generator expression:

    (Record._make(row) for row in rows)

It needs the outer parentheses.

The .extend method will accept any iterable, including list comprehensions:

    records.extend([Record._make(row) for row in rows])

and generator expressions:

    records.extend((Record._make(row) for row in rows))

In the latter case, the generator expression is the only argument of the .extend method, and Python lets us drop the pair of parentheses:

    records.extend(Record._make(row) for row in rows)

If there were another argument, it would be ambiguous and Python would complain.

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.

Its type is 'list', so it's an instance of a list, i.e. it's a list!

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. ;)

The list class has the .sort method, which sorts in-place. The 'sorted' function is a simple function that takes an iterable, iterates over it to build a list, sorts that list in-place, and then returns the list.

The oft-stated rule is that not every 2- or 3-line function needs to be a built-in, but 'sorted' is one of those cases where it's just nice to have it, a case of "practicality beats purity".

--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to