about sort and dictionary

Discussion in 'Python' started by Shi Mu, Nov 20, 2005.

  1. Shi Mu

    Shi Mu Guest

    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]
     
    Shi Mu, Nov 20, 2005
    #1
    1. Advertising

  2. Shi Mu

    Guest

    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 ;-)
     
    , Nov 20, 2005
    #2
    1. Advertising

  3. Shi Mu <> 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
     
    Eric Jacoboni, Nov 20, 2005
    #3
  4. Shi Mu

    Magnus Lycka Guest

    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
    to your program:

    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
     
    Magnus Lycka, Nov 21, 2005
    #4
  5. "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, Nov 21, 2005
    #5
  6. "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, Nov 21, 2005
    #6
  7. Shi Mu

    Duncan Booth Guest

    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.
     
    Duncan Booth, Nov 22, 2005
    #7
  8. Shi Mu

    Guest

    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.
     
    , Nov 22, 2005
    #8
  9. 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>
     
    Fredrik Lundh, Nov 22, 2005
    #9
  10. Shi Mu

    Guest

    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.
     
    , Nov 22, 2005
    #10
  11. 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


    really? wouldn't

    3
    2
    1
    3
    2
    1

    make a lot more sense ?

    </F>
     
    Fredrik Lundh, Nov 22, 2005
    #11
  12. Shi Mu

    Guest

    Fredrik Lundh wrote:
    > 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

    >
    > really? wouldn't
    >
    > 3
    > 2
    > 1
    > 3
    > 2
    > 1
    >
    > make a lot more sense ?

    I have no idea. That is my expectation. I don't know yours.

    My interpretation of it is :

    a got reversed then I consume it one by one
    a got reversed again then I consume it one by one

    Because I expect a being a mutable object, anything works on it(not
    just object method, but even other functions) is by default has side
    effect, unless otherwise stated, like copy/deepcopy.
     
    , Nov 22, 2005
    #12
  13. wrote

    > so what would an entry-level Python programmer expect from thi
    > piece of code
    >
    > for item in a.reverse()
    > print ite
    > for item in a.reverse()
    > print ite
    >
    > I would expect it to first print a in reverse then a as it was
    >
    > a=[1,2,3
    >
    > I expect it to prin
    >
    >
    >
    >
    >
    >
    >
    >

    really? wouldn'








    make a lot more sense

    </F
     
    Fredrik Lundh, Nov 22, 2005
    #13
  14. Shi Mu

    Guest

    Fredrik Lundh wrote:
    > 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
    > >

    > really? wouldn't
    >
    > 3
    > 2
    > 1
    > 3
    > 2
    > 1
    >
    > make a lot more sense ?

    Still don't see why even you ask it again. May be you can enlight me a
    bit. If this is Haskell, I would expect the result you posted.
     
    , Nov 22, 2005
    #14
  15. > Still don't see why even you ask it again.

    fyi, I'm not " -spam.invalid ", and I've
    never, as far I know, posted from "readfreenews.net"

    </F>
     
    Fredrik Lundh, Nov 22, 2005
    #15
  16. Shi Mu

    Guest

    Fredrik Lundh wrote:
    > > Still don't see why even you ask it again.

    >
    > fyi, I'm not " -spam.invalid ", and I've
    > never, as far I know, posted from "readfreenews.net"
    >

    I have no idea what you are talking about. I read this list through
    Google's group and I saw two of the same post. Google unfortunately
    just should your name "Fredrik Lundh", may be something went wrong with
    the service.
     
    , Nov 22, 2005
    #16
  17. Shi Mu

    Guest

    Fredrik Lundh wrote:
    > 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
    > >

    > really? wouldn't
    >
    > 3
    > 2
    > 1
    > 3
    > 2
    > 1
    >
    > make a lot more sense ?


    I am not a complete newb at python, but I am still pretty new.
    I too thought immediately that the output should be 3,2,1, 1,2,3.
    I used reverse() and sort() a couple time and of course read
    the docs before I did. I noted they do the change inplace, and
    don't find rememering that to be a terrible burden. Actually, I
    get rather annoyed by the comment that they return None "as
    a reminder" that the change is inplace. How arrogant! While
    I'm sure the designers had kindly intentions. my memory, though
    bad, is not that bad, and I object to being forced to write code
    that is more clunky than need be, because the designers thought
    they needed to help me with my memory.
     
    , Nov 22, 2005
    #17
  18. Fredrik Lundh wrote:

    > 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

    >
    > really? wouldn't
    >
    > 3
    > 2
    > 1
    > 3
    > 2
    > 1
    >
    > make a lot more sense ?


    Yes. The unintuitive thing is that the list is sorted in place at
    all.

    --
    --OKB (not okblacke)
    Brendan Barnwell
    "Do not follow where the path may lead. Go, instead, where there is
    no path, and leave a trail."
    --author unknown
     
    OKB (not okblacke), Nov 22, 2005
    #18
  19. On Tue, 22 Nov 2005 08:53:07 -0800, rurpy wrote:

    > I am not a complete newb at python, but I am still pretty new.
    > I too thought immediately that the output should be 3,2,1, 1,2,3.


    What you are saying is that a.reverse() should *both* change a in place
    *and* return a reference to the same list.


    > I used reverse() and sort() a couple time and of course read
    > the docs before I did. I noted they do the change inplace, and
    > don't find rememering that to be a terrible burden. Actually, I
    > get rather annoyed by the comment that they return None "as
    > a reminder" that the change is inplace. How arrogant! While
    > I'm sure the designers had kindly intentions. my memory, though
    > bad, is not that bad, and I object to being forced to write code
    > that is more clunky than need be, because the designers thought
    > they needed to help me with my memory.


    Built-in methods with side-effects (sort, reverse, update, clear, etc.)
    return None because every function must return something, not because it
    is a reminder. Python is not Pascal, and there are no procedures.

    There are four possibilities for a construction like list.sort():

    (1) sort the list in place and return a reference to the same list;
    (2) sort the list in place and return a copy of the same list;
    (3) sort the list in place and return None;
    (4) don't sort in place and return a sorted list.

    No solution is always right, no solution is always wrong, but the most
    flexible is a combination of (3) and (4). Python now has that with sort()
    and sorted(). Prior to the addition of sorted() to the language, (3) was
    considered the best solution because of a simple Python principle: never
    duplicate objects unless explicitly told to.


    --
    Steven.
     
    Steven D'Aprano, Nov 22, 2005
    #19
  20. Shi Mu

    Guest

    Steven D'Aprano wrote:
    > There are four possibilities for a construction like list.sort():
    >
    > (1) sort the list in place and return a reference to the same list;
    > (2) sort the list in place and return a copy of the same list;
    > (3) sort the list in place and return None;
    > (4) don't sort in place and return a sorted list.
    >
    > No solution is always right, no solution is always wrong, but the most
    > flexible is a combination of (3) and (4). Python now has that with sort()
    > and sorted(). Prior to the addition of sorted() to the language, (3) was
    > considered the best solution because of a simple Python principle: never
    > duplicate objects unless explicitly told to.
    >

    I don't see the reason that (3) and (4) are the most flexible.

    Again, "never duplicate objects unless explicitly told to" combined
    with "=" is name binding gives me a very strong message that
    list.sort() it will change things in place and which is why it is quite
    natural(for me at least)

    3
    2
    1
    1
    2
    3

    for this language. Wether it is "best" or make more sense doesn't
    really matter to me, though I am curious to know why.

    But basically, I just use the language as it is, and the way I want to.
    So long it solves my problem and gives me the result I want.
     
    , Nov 22, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ilias Lazaridis
    Replies:
    6
    Views:
    444
    Ilias Lazaridis
    Feb 21, 2006
  2. james_027
    Replies:
    1
    Views:
    329
    Marc 'BlackJack' Rintsch
    Aug 22, 2007
  3. Navkirat Singh
    Replies:
    6
    Views:
    3,071
    Navkirat Singh
    Jul 29, 2010
  4. Chris Rebert
    Replies:
    0
    Views:
    529
    Chris Rebert
    Jul 29, 2010
  5. Navin
    Replies:
    1
    Views:
    702
    Ken Schaefer
    Sep 9, 2003
Loading...

Share This Page