Velocity Reviews > about sort and dictionary

# about sort and dictionary

Shi Mu
Guest
Posts: n/a

 11-20-2005
Got confused by the following code:
>>> a

[6, 3, 1]
>>> b

[4, 3, 1]
>>> c

{1: [[6, 3, 1], [4, 3, 1]], 2: [[6, 3, 1]]}
>>> c[2].append(b.sort())
>>> c

{1: [[6, 3, 1], [1, 3, 4]], 2: [[6, 3, 1], None]}
#why c can not append the sorted b??
>>> b.sort()
>>> b

[1, 3, 4]

bonono@gmail.com
Guest
Posts: n/a

 11-20-2005

Shi Mu wrote:
> Got confused by the following code:
> >>> a

> [6, 3, 1]
> >>> b

> [4, 3, 1]
> >>> c

> {1: [[6, 3, 1], [4, 3, 1]], 2: [[6, 3, 1]]}
> >>> c[2].append(b.sort())
> >>> c

> {1: [[6, 3, 1], [1, 3, 4]], 2: [[6, 3, 1], None]}
> #why c can not append the sorted b??
> >>> b.sort()
> >>> b

> [1, 3, 4]

most built-in function/method don't return the "object" but None. This
I believe is the language creator's preference for everything being
explicit. You better do it like this :

b.sort()
c[2].append(b)

Of course, this make things like this not possible :

obj.method_a().method_b().method_c()

But the language(and the community) in general discourage you to write
code like this

Eric Jacoboni
Guest
Posts: n/a

 11-20-2005
Shi Mu <(E-Mail Removed)> writes:

> #why c can not append the sorted b??

Because sort() doesn't return anything?

According to the library reference:

7) The sort() and reverse() methods modify the list in place for
economy of space when sorting or reversing a large list. To remind you
that they operate by side effect, they don't return the sorted or
reversed list.

--
Eric Jacoboni, ne il y a 1435934131 secondes

Magnus Lycka
Guest
Posts: n/a

 11-21-2005
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> most built-in function/method don't return the "object" but None. This
> I believe is the language creator's preference for everything being
> explicit.

The list methods .sort() and .reverse() don't create copies,
but rather change the existing object. The reson for this is
to save RAM. If you have 512MB RAM and a 300 MB list, it's
nice that you can sort it without swapping virtual memory to
disk. That would slow down the sort operation a lot, and that
would be a shame, considering all the efforts that went into
Python's excellent sort implementation.

If you sort (or reverse) a list l, and don't need to keep the
unsorted list, you simply do l.sort() (or l.reverse()). If
you need to keep the original as well, you must make a copy
before the sort, like this: sorted_l = l[:]; sorted_l.sort().

If the sort operation had returned self, it would have been
easy to write:

sorted_l = l.sort()

and while sorted_l would contain what one might expect, it
would in fact just be another name referencing exactly the
same sorted list as l, and it would probably be surprising
that l was also sorted, and that subsequent changes would
show up in both sorted_l and l, and that sorted_l might not
be sorted and longer even though you only modified l. It's
this particular gotcha that the language creator wanted to
avoid.

With newer versions of Python, the builtin functions sorted()
and reversed() have been added, so those who think it's ugly
to call a list sorted before it actually *is* sorted, can
simply write:

sorted_l = sorted(l)

With older Python's you need to do the hard work to add this

def sorted(l): s=l[:];s.sort();return s
def reversed(l): r=l[:];r.reverse();return r

Actually, I guess it's possible that sorted() is done so
that it works like below, but I don't think pre-sorted()
versions of Python support keyword arguments to list.sort()
anyway...

def sorted(l, *p, **kw): s=l[:];s.sort(*p, **kw);return s

George Sakkis
Guest
Posts: n/a

 11-21-2005
"Shi Mu" wrote:

> Got confused by the following code:
> >>> a

[6, 3, 1]
> >>> b

[4, 3, 1]
> >>> c

> {1: [[6, 3, 1], [4, 3, 1]], 2: [[6, 3, 1]]}
> >>> c[2].append(b.sort())
> >>> c

> {1: [[6, 3, 1], [1, 3, 4]], 2: [[6, 3, 1], None]}
> #why c can not append the sorted b??

In python 2.4, you can use the sorted() builtin instead:

c[2].append(sorted(b))

George

George Sakkis
Guest
Posts: n/a

 11-21-2005
"Shi Mu" wrote:

> Got confused by the following code:
> >>> a

[6, 3, 1]
> >>> b

[4, 3, 1]
> >>> c

> {1: [[6, 3, 1], [4, 3, 1]], 2: [[6, 3, 1]]}
> >>> c[2].append(b.sort())
> >>> c

> {1: [[6, 3, 1], [1, 3, 4]], 2: [[6, 3, 1], None]}
> #why c can not append the sorted b??

In python 2.4, you can use the sorted() builtin instead:

c[2].append(sorted(b))

George

Duncan Booth
Guest
Posts: n/a

 11-22-2005
Magnus Lycka wrote:

> Actually, I guess it's possible that sorted() is done so
> that it works like below, but I don't think pre-sorted()
> versions of Python support keyword arguments to list.sort()
> anyway...
>
> def sorted(l, *p, **kw): s=l[:];s.sort(*p, **kw);return s

One part you missed, sorted is actually closer to:

def sorted(iterable, cmp=None, key=None, reverse=False):
"sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list"
s=list(iterable)
s.sort(cmp, key, reverse)
return s

The point being that while in general only a list will have a sort
method, the sorted builtin may be called on any iterable and will
return a sorted list.

Also note that it only accepts specific named arguments, and has a
docstring.

bonono@gmail.com
Guest
Posts: n/a

 11-22-2005

Magnus Lycka wrote:
> sorted_l = l.sort()
>
> and while sorted_l would contain what one might expect, it
> would in fact just be another name referencing exactly the
> same sorted list as l, and it would probably be surprising
> that l was also sorted, and that subsequent changes would
> show up in both sorted_l and l, and that sorted_l might not
> be sorted and longer even though you only modified l. It's
> this particular gotcha that the language creator wanted to
> avoid.
>

Since python's '=' is just name binding and that most objects(other
than those like int/float/string?) are mutable, I don't quite
understand why this is a gotcha that is so worrying.

a = [1,2,3]
a.sorted()
b = a

even an entry level python programmer can't expect 'b' to be
unchanged(after getting the first bite may be) if there is any
operation on a later. This not only applies to list but almost all
mutable object.

As you said, if one wants a copy of an object, use copy/deepcopy or
even pickle to get a snapshot of it.

Fredrik Lundh
Guest
Posts: n/a

 11-22-2005
(E-Mail Removed) wrote:

> Since python's '=' is just name binding and that most objects(other
> than those like int/float/string?) are mutable, I don't quite
> understand why this is a gotcha that is so worrying.
>
> a = [1,2,3]
> a.sorted()
> b = a
>
> even an entry level python programmer can't expect 'b' to be
> unchanged(after getting the first bite may be) if there is any
> operation on a later. This not only applies to list but almost all
> mutable object.

so what would an entry-level Python programmer expect from this
piece of code?

for item in a.reverse():
print item
for item in a.reverse():
print item

(as the X people used to say, the only thing worse than generalizing
from one example (sort) is generalizing from no examples at all ("let's
assume I have a use case")).

</F>

bonono@gmail.com
Guest
Posts: n/a

 11-22-2005

Fredrik Lundh wrote:
> so what would an entry-level Python programmer expect from this
> piece of code?
>
> for item in a.reverse():
> print item
> for item in a.reverse():
> print item
>

I would expect it to first print a in reverse then a as it was.

a=[1,2,3]

I expect it to print

3
2
1
1
2
3

As for your other comment, I don't even understand them.