Why doesn't python's list append() method return the list itself?

Discussion in 'Python' started by dhruvbird, Jul 11, 2010.

  1. dhruvbird

    dhruvbird Guest

    Why doesn't python's list append() method return the list itself? For
    that matter, even the reverse() and sort() methods?
    I found this link (http://code.google.com/edu/languages/google-python-
    class/lists.html) which suggests that this is done to make sure that
    the programmer understands that the list is being modified in place,
    but that rules out constructs like:
    ([1,2,3,4].reverse()+[[]]).reverse()
    I want to prepend an empty list to [1,2,3,4]. This is just a toy
    example, since I can always do that with [[]]+[1,2,3,4].

    Regards,
    -Dhruv.
     
    dhruvbird, Jul 11, 2010
    #1
    1. Advertising

  2. On 07/11/2010 05:59 PM, dhruvbird wrote:
    > Why doesn't python's list append() method return the list itself? For
    > that matter, even the reverse() and sort() methods?
    > I found this link (http://code.google.com/edu/languages/google-python-
    > class/lists.html) which suggests that this is done to make sure that
    > the programmer understands that the list is being modified in place,


    Yes!

    > but that rules out constructs like:
    > ([1,2,3,4].reverse()+[[]]).reverse()


    No!

    you can either approach this by imperatively modifying a list in-place:

    L = [1,2,3,4]
    L.reverse()
    L.append([])
    L.reverse()

    Or you can use a more functional style:

    L2 = reversed(reversed([1,2,3,4]) + [[]])

    (or ([1,2,3,4][::-1]+[[]])[::-1], if you like that kind of thing)

    Imagine list.reverse and list.append *did* return self:

    L1 = [1,2,3,4]
    L2 = L1.reverse().append([]).reverse()

    would you expect, after this code, that (L1 == L2) and (L1 is L2)? I
    think it would surprise a lot of people. Better clearly separate
    modifying an object and functionally processing an object.


    Cheers

    Thomas
     
    Thomas Jollans, Jul 11, 2010
    #2
    1. Advertising

  3. On 07/11/2010 06:28 PM, Nathan Rice wrote:
    > Do list(reversed(list(reversed([1, 2, 3, 4])) + [[]]))
    >
    > Though TBH sometimes get annoyed at this behavior myself. There are a
    > lot of people who are very vocal in support of returning none, and it
    > makes sense in some ways. Since reversed returns an iterator though, it
    > makes this code horrible and unreadable.
    >


    ah yes, forgot about that nuance. casting reversed to list. Still, there
    is slicing.
     
    Thomas Jollans, Jul 11, 2010
    #3
  4. On Sun, 11 Jul 2010 08:59:06 -0700 (PDT)
    dhruvbird <> wrote:
    > Why doesn't python's list append() method return the list itself? For
    > that matter, even the reverse() and sort() methods?
    > I found this link (http://code.google.com/edu/languages/google-python-
    > class/lists.html) which suggests that this is done to make sure that
    > the programmer understands that the list is being modified in place,
    > but that rules out constructs like:
    > ([1,2,3,4].reverse()+[[]]).reverse()
    > I want to prepend an empty list to [1,2,3,4]. This is just a toy
    > example, since I can always do that with [[]]+[1,2,3,4].


    >>> x = [1,2,3,4]
    >>> y = [5,6]
    >>> x[:0] = y
    >>> x

    [5, 6, 1, 2, 3, 4]
     
    Antoine Pitrou, Jul 11, 2010
    #4
  5. dhruvbird

    MRAB Guest

    Thomas Jollans wrote:
    > On 07/11/2010 05:59 PM, dhruvbird wrote:
    >> Why doesn't python's list append() method return the list itself? For
    >> that matter, even the reverse() and sort() methods?
    >> I found this link (http://code.google.com/edu/languages/google-python-
    >> class/lists.html) which suggests that this is done to make sure that
    >> the programmer understands that the list is being modified in place,

    >
    > Yes!
    >
    >> but that rules out constructs like:
    >> ([1,2,3,4].reverse()+[[]]).reverse()

    >
    > No!
    >
    > you can either approach this by imperatively modifying a list in-place:
    >
    > L = [1,2,3,4]
    > L.reverse()
    > L.append([])
    > L.reverse()
    >

    [snip]
    If you want to prepend an empty list in-place, use the .insert method:

    L = [1,2,3,4]
    L.insert(0, [])
     
    MRAB, Jul 11, 2010
    #5
  6. dhruvbird

    dhruvbird Guest

    On Jul 11, 9:19 pm, Thomas Jollans <> wrote:
    > On 07/11/2010 05:59 PM, dhruvbird wrote:
    >
    > > Why doesn't python's list append() method return the list itself? For
    > > that matter, even the reverse() and sort() methods?
    > > I found this link (http://code.google.com/edu/languages/google-python-
    > > class/lists.html) which suggests that this is done to make sure that
    > > the programmer understands that the list is being modified in place,

    >
    > Yes!
    >
    > > but that rules out constructs like:
    > > ([1,2,3,4].reverse()+[[]]).reverse()

    >
    > No!
    >
    > you can either approach this by imperatively modifying a list in-place:
    >
    > L = [1,2,3,4]
    > L.reverse()
    > L.append([])
    > L.reverse()
    >
    > Or you can use a more functional style:
    >
    > L2 = reversed(reversed([1,2,3,4]) + [[]])


    Okay, but this assumes that I have reversed/sorted/etc... type of
    functions for all member functions that mutate the container.
    Also, as Nathan mentioned, reversed returns an iterator, whereas
    sorted returns a list. This asymmertic behaviour is a bit unnerving.

    >
    > (or ([1,2,3,4][::-1]+[[]])[::-1], if you like that kind of thing)
    >
    > Imagine list.reverse and list.append *did* return self:
    >
    > L1 = [1,2,3,4]
    > L2 = L1.reverse().append([]).reverse()
    >
    > would you expect, after this code, that (L1 == L2) and (L1 is L2)? I
    > think it would surprise a lot of people. Better clearly separate
    > modifying an object and functionally processing an object.


    I think this is a fair call. Honestly, I wouldn't expect them to be
    the same.

    However, there are cases when I want to be able to write down my
    intent in one line.
    Much like f(g(h(x))).

    On a side note, is there any other way to append to a list using
    slices (apart from the one below):
    x[len(x):len(x)] = [item to append]

    And while we are talking about python here, why does this statement:
    y = x[:0] = [100] behave the way it does?
    I mean everything except for the last value is assigned to the last
    value rather than the assignments following the chain and every item
    getting its succeeding item's reference?

    Regards,
    -Dhruv.
     
    dhruvbird, Jul 11, 2010
    #6
  7. dhruvbird

    News123 Guest

    dhruvbird wrote:

    >
    > On a side note, is there any other way to append to a list using
    > slices (apart from the one below):
    > x[len(x):len(x)] = [item to append]



    dy you mean
    x.extend([1,2,3])

    ?
     
    News123, Jul 12, 2010
    #7
  8. On Jul 11, 8:59 am, dhruvbird <> wrote:
    > Why doesn't python's list append() method return the list itself? For
    > that matter, even the reverse() and sort() methods?


    Because Guido thinks that having those methods return None is the best
    way to communicate that the underlying object has been mutated in-
    place.

    Some other languages do it differently, but this is Guido's language,
    so we do it his way.


    Raymond
     
    Raymond Hettinger, Jul 12, 2010
    #8
  9. On 7/11/10 10:03 PM, Nathan Rice wrote:
    > Yeah, I long ago filed the in place place in the same folder as
    > strings-as-sequences, all() returning True for an empty iterable and any
    > returning True rather than the thing which triggered it.


    You know, the latter two I can see an argument for, and could see the
    usefulness therein -- though I've never used either like that, but I
    consider that chance. I could see the use (and could readily write my
    own all/any in such a case, then keep it in my toolbox).

    But the first: what?!

    for ch in data:

    is exceptionally useful. Strings-as-sequences I've used hundreds,
    thousands of times. I use it constantly.

    --

    Stephen Hansen
    ... Also: Ixokai
    ... Mail: me+list/python (AT) ixokai (DOT) io
    ... Blog: http://meh.ixokai.io/


    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v2.0.10 (Darwin)

    iQEcBAEBAgAGBQJMOqO/AAoJEKcbwptVWx/l5JAIAKbwN8lf7BeNRZw6O2Ipy8Nb
    StvFHOuWSnSBjuRacr6Zr9ARY8BGIbMH3hBQrWXzYtqDrIhv1ZRvntjeqcJkByEj
    DRBAzka6ZtxIVeBmpYlmd+IPNEiZhhGLSRjd8W0eeCUKHTlYWC4GPx/CeU6mAPPy
    3szrc6YvWMSm1YK9G6j7Rt4pLfkmnHkn6MObmGZYTUzLpnoKzG2DNctWamkDwdyM
    xNd5mbW8g85xKxWT1GRG6c2M58yP1LJlsra+KlwMWqGtQ8EVxLBr5uQX6gotVvkl
    B5EV2btshgULmhtGwxX0PB7G7Uk3JVJK91OWPbL5T1m1X5XqSwAv2BctTuqSaZ4=
    =thSD
    -----END PGP SIGNATURE-----
     
    Stephen Hansen, Jul 12, 2010
    #9
  10. dhruvbird

    Chris Rebert Guest

    On Sun, Jul 11, 2010 at 10:03 PM, Nathan Rice
    <> wrote:
    > Yeah, I long ago filed the in place place in the same folder as

    <snip>
    > all() returning True for an empty iterable


    If you weren't taught about vacuous truth (or even identity elements)
    in Discrete Mathematics, someone fscked up. Said behavior is the
    absolute correct behavior from a formal logic standpoint.

    Cheers,
    Chris
    --
    http://blog.rebertia.com
     
    Chris Rebert, Jul 12, 2010
    #10
  11. dhruvbird

    dhruvbird Guest

    On Jul 12, 5:30 am, News123 <> wrote:
    > dhruvbird wrote:
    >
    > > On a side note, is there any other way to append to a list using
    > > slices (apart from the one below):
    > > x[len(x):len(x)] = [item to append]

    >
    > dy you mean
    > x.extend([1,2,3])


    No, I meant x.append(4)
    Except that I want to accomplish it using slices.

    (I can do it as x[lex(x):] = [item_to_append] but is there any other
    way?)

    Regards,
    -Dhruv.
     
    dhruvbird, Jul 12, 2010
    #11
  12. dhruvbird <> writes:

    > No, I meant x.append(4)
    > Except that I want to accomplish it using slices.
    >
    > (I can do it as x[lex(x):] = [item_to_append] but is there any other
    > way?)


    It seems that you've found a way to do so, so why do you need another
    way? Are you after elegance? Efficiency? Brevity?

    Here are some other ways to express the same, and all use slices in some
    way:

    x[slice(len(x), None)] = [item_to_append]
    x.__setitem__(slice(len(x), None), [item_to_append])
    x.__setslice__(len(x), len(x), [item_to_append])

    ....but I have no idea why any of them would make any more sense than
    x[len(x):] = [item_to_append].
     
    Hrvoje Niksic, Jul 12, 2010
    #12
  13. dhruvbird

    dhruvbird Guest

    On Jul 12, 4:20 pm, Hrvoje Niksic <> wrote:
    > dhruvbird <> writes:
    > > No, I meant x.append(4)
    > > Except that I want to accomplish it using slices.

    >
    > > (I can do it as x[lex(x):] = [item_to_append] but is there any other
    > > way?)

    >
    > It seems that you've found a way to do so, so why do you need another
    > way?  Are you after elegance?  Efficiency?  Brevity?


    Actually, the reason I ask is because I think a lot of things can be
    done using slices and its support for negative indexes. Basically
    putting constants in the slices (as opposed to variables like len(x),
    etc... which depend upon the variable name). So, was just trying to
    cogitate on whether append can be implemented that way or not.

    Regards,
    -Dhruv.
     
    dhruvbird, Jul 12, 2010
    #13
  14. dhruvbird

    John Nagle Guest

    On 7/11/2010 5:24 PM, Steven D'Aprano wrote:
    > On Sun, 11 Jul 2010 08:59:06 -0700, dhruvbird wrote:
    >
    >> Why doesn't python's list append() method return the list itself? For
    >> that matter, even the reverse() and sort() methods? I found this link
    >> (http://code.google.com/edu/languages/google-python- class/lists.html)
    >> which suggests that this is done to make sure that the programmer
    >> understands that the list is being modified in place, but that rules out
    >> constructs like:
    >> ([1,2,3,4].reverse()+[[]]).reverse()

    >
    > Yes. So what? Where's the problem?
    >
    > List methods work in place.

    ....
    > Not everything needs to be a one-liner.


    It's interesting that all Python functions are considered to
    return a value. Arguably, if a function just does a "return",
    it should be an error to try to use its return value.

    Some languages have a very functional orientation, and
    everything is considered to return some value, even
    control structures. LISP is like that. But Python isn't
    one of those languages.

    John Nagle
     
    John Nagle, Jul 12, 2010
    #14
  15. John Nagle wrote:
    > Arguably, if a function just does a "return",
    > it should be an error to try to use its return value.


    It's been suggested at least once before that the
    default return value for a function should be some
    special value that raises an exception if you try
    to do anything with it except throw it away.

    Unfortunately, the existence of such a value would
    cause headaches for things like debuggers that need
    to be able to deal with anything at all without
    blowing up.

    --
    Greg
     
    Gregory Ewing, Jul 13, 2010
    #15
  16. dhruvbird

    Aahz Guest

    [Original not available on my swerver, responding here]

    >On 7/11/10 10:03 PM, Nathan Rice wrote:
    >>
    >> Yeah, I long ago filed the in place place in the same folder as
    >> strings-as-sequences, all() returning True for an empty iterable and any
    >> returning True rather than the thing which triggered it.


    Because I love to repeat myself:

    "...string iteration isn't about treating strings as sequences of strings,
    it's about treating strings as sequences of characters. The fact that
    characters are also strings is the reason we have problems, but characters
    are strings for other good reasons." --Aahz
    http://mail.python.org/pipermail/python-3000/2006-April/000897.html

    Do you really want to give up Python's lovely string-slicing
    capabilities?
    --
    Aahz () <*> http://www.pythoncraft.com/

    "....Normal is what cuts off your sixth finger and your tail..." --Siobhan
     
    Aahz, Jul 14, 2010
    #16
  17. dhruvbird

    John Nagle Guest

    On 7/13/2010 4:22 AM, Gregory Ewing wrote:
    > John Nagle wrote:
    >> Arguably, if a function just does a "return",
    >> it should be an error to try to use its return value.

    >
    > It's been suggested at least once before that the
    > default return value for a function should be some
    > special value that raises an exception if you try
    > to do anything with it except throw it away.


    Treating that case as an error would be consistent with the
    way attribute access works in Python. In Python, attempting
    to access a nonexistent attribute raises an exception. In
    Javascript, that returns a null. Javascript makes no
    distinction between "null" and "nonexistent", but Python
    does.

    It's un-Pythonic and inconsistent that functions which
    return nothing are considered to return a None object.

    John Nagle
     
    John Nagle, Jul 16, 2010
    #17
    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. Replies:
    3
    Views:
    414
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,076
    Smokey Grindel
    Dec 2, 2006
  3. Z
    Replies:
    12
    Views:
    5,005
    Knute Johnson
    Feb 19, 2007
  4. HYRY
    Replies:
    10
    Views:
    627
    Bruno Desthuilliers
    Sep 26, 2007
  5. equation .
    Replies:
    27
    Views:
    1,413
    Joshua Maurice
    Jan 11, 2011
Loading...

Share This Page