Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

append on lists

4 views
Skip to first unread message

Armin

unread,
Sep 15, 2008, 4:24:39 PM9/15/08
to

Hi,

just a dumb question.

Let a = [1,2,3,4,5]

Why is the value of a.append(7) equal None and not [1,2,3,4,5,6,7] ??

--Armin

Fredrik Lundh

unread,
Sep 15, 2008, 4:17:37 PM9/15/08
to pytho...@python.org
Armin wrote:

yeah, that's a dumb question.

</F>

Armin

unread,
Sep 15, 2008, 4:35:36 PM9/15/08
to

yeah, that's a dumb answer.

Chris Rebert

unread,
Sep 15, 2008, 4:21:31 PM9/15/08
to Armin, pytho...@python.org
I'll assume the presence of the 6 is a typo.

Because .append() mutates 'a' and appends the item in-place rather
than creating and returning a new list with the item appended, and
it's good Python style for mutating methods to have no return value
(since all functions must have some return value, Python uses None
when the function doesn't explicitly return anything).

If you print 'a' after doing the .append(), you'll see it's changed to
your desired value.

Regards,
Chris

>
> --Armin
> --
> http://mail.python.org/mailman/listinfo/python-list
>
--
Follow the path of the Iguana...
http://rebertia.com

Arnaud Delobelle

unread,
Sep 15, 2008, 4:22:06 PM9/15/08
to

Because list.append is a method that mutates its object, and such
method usually return None. What you should check is the value of 'a'
after 'a.append(7)'.

--
Arnaud

Jerry Hill

unread,
Sep 15, 2008, 4:23:51 PM9/15/08
to pytho...@python.org
On Mon, Sep 15, 2008 at 4:24 PM, Armin <a...@nospam.org> wrote:
> Why is the value of a.append(7) equal None and not [1,2,3,4,5,6,7] ??

Because the list a has been altered in place.

--
Jerry

Armin

unread,
Sep 15, 2008, 4:45:38 PM9/15/08
to
Chris Rebert wrote:
> On Mon, Sep 15, 2008 at 1:24 PM, Armin <a...@nospam.org> wrote:
>>
>> Hi,
>>
>> just a dumb question.
>>
>> Let a = [1,2,3,4,5]
>>
>> Why is the value of a.append(7) equal None and not [1,2,3,4,5,6,7] ??
> I'll assume the presence of the 6 is a typo.

Sorry, that's the case.

>
> Because .append() mutates 'a' and appends the item in-place rather
> than creating and returning a new list with the item appended, and
> it's good Python style for mutating methods to have no return value
> (since all functions must have some return value, Python uses None
> when the function doesn't explicitly return anything).

Yes, but this is very unconvenient.
If d should reference the list a extended with a single list element
you need at least two lines

a.append(7)
d=a

and not more intuitive d = a.append(7)

--Armin

Fredrik Lundh

unread,
Sep 15, 2008, 4:32:18 PM9/15/08
to pytho...@python.org
Armin wrote:

>>> just a dumb question.
>>>
>>> Let a = [1,2,3,4,5]
>>>
>>> Why is the value of a.append(7) equal None and not [1,2,3,4,5,6,7] ??
>>
>> yeah, that's a dumb question.
>

> yeah, that's a dumb answer.

did you read your own post? I did.

</F>

Grant Edwards

unread,
Sep 15, 2008, 4:40:50 PM9/15/08
to
On 2008-09-15, Armin <a...@nospam.org> wrote:

>> Because .append() mutates 'a' and appends the item in-place rather
>> than creating and returning a new list with the item appended, and
>> it's good Python style for mutating methods to have no return value
>> (since all functions must have some return value, Python uses None
>> when the function doesn't explicitly return anything).
>
> Yes, but this is very unconvenient.

Aw, admit it -- it's not _that_ inconvenient.

> If d should reference the list a extended with a single list
> element you need at least two lines
>
> a.append(7)
> d=a

With that usage it's obvious that a is mutated, and now both
"a" and "d" are bound to the same extended list.

> and not more intuitive d = a.append(7)

Becase that usage implies (at least to many of us) that "a" is
unchanged, and that "d" is now bound to a different object than
"a".

--
Grant Edwards grante Yow! Where's th' DAFFY
at DUCK EXHIBIT??
visi.com

Fredrik Lundh

unread,
Sep 15, 2008, 4:43:00 PM9/15/08
to pytho...@python.org
Armin wrote:

> If d should reference the list a extended with a single list element
> you need at least two lines
>
> a.append(7)
> d=a

why do you need two names for the same thing?

> and not more intuitive d = a.append(7)

unless you completely change the semantics of "append", your code would
modify "a" as well. how is that "more intuitive"?

side effects are bad as they are, but side effects in unexpected places
is a really lousy idea. I don't think you've thought this one through,
really.

</F>

John Machin

unread,
Sep 15, 2008, 4:47:24 PM9/15/08
to
On Sep 16, 6:45 am, Armin <a...@nospam.org> wrote:

> Yes, but this is very unconvenient.
> If d should reference the list a extended with a single list element
> you need at least two lines
>
> a.append(7)
> d=a
>
> and not more intuitive d = a.append(7)

Methods/functions which return a value other than the formal None and
also mutate their environment are "a snare and a delusion". Don't wish
for them.

Inconvenient? How often do you want to mutate a list and then set up
another reference to it?

Chris Rebert

unread,
Sep 15, 2008, 4:47:53 PM9/15/08
to Armin, pytho...@python.org
On Mon, Sep 15, 2008 at 1:45 PM, Armin <a...@nospam.org> wrote:
> Chris Rebert wrote:
>>
>> On Mon, Sep 15, 2008 at 1:24 PM, Armin <a...@nospam.org> wrote:
>>>
>>> Hi,
>>>
>>> just a dumb question.
>>>
>>> Let a = [1,2,3,4,5]
>>>
>>> Why is the value of a.append(7) equal None and not [1,2,3,4,5,6,7] ??
>>
>> I'll assume the presence of the 6 is a typo.
>
> Sorry, that's the case.
>
>>
>> Because .append() mutates 'a' and appends the item in-place rather
>> than creating and returning a new list with the item appended, and
>> it's good Python style for mutating methods to have no return value
>> (since all functions must have some return value, Python uses None
>> when the function doesn't explicitly return anything).
>
> Yes, but this is very unconvenient.
> If d should reference the list a extended with a single list element
> you need at least two lines
>
> a.append(7)
> d=a
>
> and not more intuitive d = a.append(7)

And then they'd both reference the same list and you'd run into all
sorts of problems.

The code you'd actually want is:

d = a[:] #copy a
d.append(7)

Or if you're willing to overlook the inefficiency:

d = a + [7]

But that's not idiomatic.

And debating the fundamentals of the language, which aren't going to
change anytime soon, isn't going to get you anywhere.
You may be interested in looking at Python's "tuple" datatype, which
is basically an immutable list.

I'd also suggest you Read The Fine Tutorial, and that your original
question was better suited to IRC or python-tutors
(http://mail.python.org/mailman/listinfo/tutor) than this mailinglist.

Regards,
Chris

>
> --Armin
>
>
>>
>> If you print 'a' after doing the .append(), you'll see it's changed to
>> your desired value.
>
>
>>
>> Regards,
>> Chris
>>
>>> --Armin
>>> --
>>> http://mail.python.org/mailman/listinfo/python-list
>>>

Jerry Hill

unread,
Sep 15, 2008, 4:50:18 PM9/15/08
to pytho...@python.org
On Mon, Sep 15, 2008 at 4:45 PM, Armin <a...@nospam.org> wrote:
> Yes, but this is very unconvenient.
> If d should reference the list a extended with a single list element
> you need at least two lines

You do it in two lines, because you're doing two different things.

> a.append(7)

This appends the element 7 to the list a.

> d=a

This binds the name d to the same list as a is bound to. If you wand
d to point to a new list with the same contents as the list a, plus
the number 7 do this:

d = a + [7]

Here's an example of the difference:
>>> a = range(6)
>>> a
[0, 1, 2, 3, 4, 5]
>>> a.append(7)
>>> a
[0, 1, 2, 3, 4, 5, 7]
>>> d = a
>>> d
[0, 1, 2, 3, 4, 5, 7]
>>> d.append(10)
>>> a
[0, 1, 2, 3, 4, 5, 7, 10]
>>> d
[0, 1, 2, 3, 4, 5, 7, 10]
>>>

See how a and d are two names bound to the same list?

Here's the other way:
>>> a = range(6)


>>> d = a + [7]

>>> a
[0, 1, 2, 3, 4, 5]
>>> d
[0, 1, 2, 3, 4, 5, 7]
>>> d.append(10)
>>> a
[0, 1, 2, 3, 4, 5]
>>> d
[0, 1, 2, 3, 4, 5, 7, 10]
>>>

--
Jerry

Steven D'Aprano

unread,
Sep 15, 2008, 7:03:59 PM9/15/08
to
On Mon, 15 Sep 2008 13:47:53 -0700, Chris Rebert wrote:

> The code you'd actually want is:
>
> d = a[:] #copy a
> d.append(7)
>
> Or if you're willing to overlook the inefficiency:
>
> d = a + [7]
>
> But that's not idiomatic.

Why is a + [7] more inefficient than manually copying the list and
appending to the copy? Surely both pieces of code end up doing the same
thing?

In fact, I'd guess that the second is likely to be marginally more
efficient than the first:


>>> x = compile('d = a[:]; d.append(7)', '', 'exec')
>>> dis.dis(x)
1 0 LOAD_NAME 0 (a)
3 SLICE+0
4 STORE_NAME 1 (d)
7 LOAD_NAME 1 (d)
10 LOAD_ATTR 2 (append)
13 LOAD_CONST 0 (7)
16 CALL_FUNCTION 1
19 POP_TOP
20 LOAD_CONST 1 (None)
23 RETURN_VALUE

>>> x = compile('d = a + [7]', '', 'exec')
>>> dis.dis(x)
1 0 LOAD_NAME 0 (a)
3 LOAD_CONST 0 (7)
6 BUILD_LIST 1
9 BINARY_ADD
10 STORE_NAME 1 (d)
13 LOAD_CONST 1 (None)
16 RETURN_VALUE


timeit agrees with me:

>>> from timeit import Timer
>>> t1 = Timer('d = a[:]; d.append(7)', 'a = []')
>>> t2 = Timer('d = a + [7]', 'a = []')
>>> t1.repeat(number=1000)
[0.0015339851379394531, 0.0014910697937011719, 0.0014841556549072266]
>>> t2.repeat(number=1000)
[0.0011889934539794922, 0.0013048648834228516, 0.0013070106506347656]


--
Steven

Chris Rebert

unread,
Sep 15, 2008, 8:08:30 PM9/15/08
to Steven D'Aprano, pytho...@python.org
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Sorry, I was just speculating based on the extraneous list ([7]) used
in the second one.
My bad. :)

Regards,
Chris

Peter Anderson

unread,
Sep 16, 2008, 1:03:51 AM9/16/08
to pytho...@python.org
"/... I don't think you've thought this one through, really./"

Is this kind of response really necessary? The original post was asking
(from his perspective at least) a legitimate question. To a Python
expert it may be a "silly question" but replying in such a fatuous way
puts off those "less gifted" from using this excellent reference source.
Nobody enjoys being spoken to like this.

We ought to try and be a little kinder to others on the list, don't you
think? :-)

Regards,
Peter
--
*Peter Anderson*
There is nothing more difficult to take in hand, more perilous to
conduct, or more uncertain in its success, than to take the lead in the
introduction of a new order of things—Niccolo Machiavelli, /The Prince/,
ch. 6

tony.c...@googlemail.com

unread,
Sep 16, 2008, 1:58:10 AM9/16/08
to
On Sep 16, 6:03 am, Peter Anderson <peter.ander...@internode.on.net>
wrote:

> "/... I don't think you've thought this one through, really./"
> snip

>
> We ought to try and be a little kinder to others on the list, don't you
> think? :-)
>
> snip

Well said!
Tony

Armin

unread,
Sep 16, 2008, 4:20:19 AM9/16/08
to
John Machin wrote:
> On Sep 16, 6:45 am, Armin <a...@nospam.org> wrote:
>
>> Yes, but this is very unconvenient.
>> If d should reference the list a extended with a single list element
>> you need at least two lines
>>
>> a.append(7)
>> d=a
>>
>> and not more intuitive d = a.append(7)
>
> Methods/functions which return a value other than the formal None and
> also mutate their environment are "a snare and a delusion". Don't wish
> for them.

c = [9,10]
[1,2,3,4,7].append(c) -> Is this a valid expression?

The 'value' of that expression is None.

However ... that's the way of the implementation of the append method.
It's a little bit confusing to me ...

--Armin

Thanks to all !

Chris Rebert

unread,
Sep 16, 2008, 4:15:08 AM9/16/08
to Armin, pytho...@python.org
On Tue, Sep 16, 2008 at 1:20 AM, Armin <a...@nospam.org> wrote:
> John Machin wrote:
>>
>> On Sep 16, 6:45 am, Armin <a...@nospam.org> wrote:
>>
>>> Yes, but this is very unconvenient.
>>> If d should reference the list a extended with a single list element
>>> you need at least two lines
>>>
>>> a.append(7)
>>> d=a
>>>
>>> and not more intuitive d = a.append(7)
>>
>> Methods/functions which return a value other than the formal None and
>> also mutate their environment are "a snare and a delusion". Don't wish
>> for them.
>
>
>
> c = [9,10]
> [1,2,3,4,7].append(c) -> Is this a valid expression?

Literally, no, because you can't call methods on literals.
However, the sentiment is valid, though probably not what you want:

>>> c = [9,10]
>>> a = [1,2,3,4,7]
>>> b = a[:]
>>> a.append(c)
>>> a #note the nested list
[1, 2, 3, 4, 7, [9, 10]]
>>> b
[1, 2, 3, 4, 7]
>>> b.extend(c)
>>> b
[1, 2, 3, 4, 7, 9, 10]

Regards,
Chris

>
> The 'value' of that expression is None.
>
> However ... that's the way of the implementation of the append method.
> It's a little bit confusing to me ...
>
> --Armin
>
> Thanks to all !
>
>
>>
>> Inconvenient? How often do you want to mutate a list and then set up
>> another reference to it?
>>

Hrvoje Niksic

unread,
Sep 16, 2008, 4:48:42 AM9/16/08
to
"Chris Rebert" <c...@rebertia.com> writes:

>> c = [9,10]
>> [1,2,3,4,7].append(c) -> Is this a valid expression?
>
> Literally, no, because you can't call methods on literals.

This is in fact not true. [1,2,3,4,7].append([9, 10]) is a perfectly
valid expression, only it doesn't do much (that you can observe).

The canonical response (no doubt already quoted in this thread) is
that returning the list from append would confuse the hell out of
people who expect a copy of the list, such as:

a = [1, 2, 3]
b = a.append(4)
# if the above "worked" in the sense that b == [1, 2, 3, 4], I for one
# would expect a to remain unchanged

Duncan Booth

unread,
Sep 16, 2008, 4:55:36 AM9/16/08
to
"Chris Rebert" <c...@rebertia.com> wrote:
> On Tue, Sep 16, 2008 at 1:20 AM, Armin <a...@nospam.org> wrote:
>> [1,2,3,4,7].append(c) -> Is this a valid expression?
>
> Literally, no, because you can't call methods on literals.

Rubbish. There is no restriction about calling methods on literals. That
expression is perfectly valid but has no practical use that I can see.

There is a syntax gotcha which you may have been thinking of: to call a
method on an integer literal (or indeed to access any attribute) you have
to use whitespace between the literal and the dot otherwise you have a
float literal and a syntax error.

>>> 5 .__hex__()
'0x5'

The only relatively common use I can think of where you might want to call
a method directly on a literal is to produce a list of strings while being
lazy about the typing:

COLOURS = "red green blue pink yellow".split()

versus

COLOURS = ["red", "green", "blue", "pink", "yellow"]


--
Duncan Booth http://kupuguy.blogspot.com

Hrvoje Niksic

unread,
Sep 16, 2008, 5:03:59 AM9/16/08
to
Duncan Booth <duncan...@invalid.invalid> writes:

> The only relatively common use I can think of where you might want to call
> a method directly on a literal is to produce a list of strings while being
> lazy about the typing:

By far the most common is probably 'sep'.join(iterable).

Alex Marandon

unread,
Sep 16, 2008, 6:15:48 AM9/16/08
to
Armin wrote:
> Chris Rebert wrote:
>> On Mon, Sep 15, 2008 at 1:24 PM, Armin <a...@nospam.org> wrote:
>>>
>>> Hi,
>>>
>>> just a dumb question.
>>>
>>> Let a = [1,2,3,4,5]
>>>
>>> Why is the value of a.append(7) equal None and not [1,2,3,4,5,6,7] ??
>>
>> Because .append() mutates 'a' and appends the item in-place rather
>> than creating and returning a new list with the item appended, and
>> it's good Python style for mutating methods to have no return value
>> (since all functions must have some return value, Python uses None
>> when the function doesn't explicitly return anything).
>
> Yes, but this is very unconvenient.

Hi,

You might be interested in using the + operator instead of append. You
could also define your own list type, based on the UserList included in
the standard library.

>>> from UserList import UserList
>>> class MyList(UserList):
... def my_append(self, value):
... return self + [value]
...
>>> l = MyList([1,2,3,4])
>>> l
[1, 2, 3, 4]
>>> l.my_append(5)
[1, 2, 3, 4, 5]
>>> l
[1, 2, 3, 4]

Armin

unread,
Sep 16, 2008, 7:10:37 AM9/16/08
to
Duncan Booth wrote:
> "Chris Rebert" <c...@rebertia.com> wrote:
>> On Tue, Sep 16, 2008 at 1:20 AM, Armin <a...@nospam.org> wrote:
>>> [1,2,3,4,7].append(c) -> Is this a valid expression?
>> Literally, no, because you can't call methods on literals.
>
> Rubbish. There is no restriction about calling methods on literals. That
> expression is perfectly valid but has no practical use that I can see.

The semantic of [1,2,3,4,7].append(c) and [1,2,3,4,7] + c
(with c = [8,9]) is identical, but the first expression doesn't provide
a value. Strange by design ...

--Armin

Alex Marandon

unread,
Sep 16, 2008, 7:22:46 AM9/16/08
to
Armin wrote:

> Duncan Booth wrote:
>
> The semantic of [1,2,3,4,7].append(c) and [1,2,3,4,7] + c
> (with c = [8,9]) is identical,

No it's not, + doesn't alter its operands.

>>> a = 1
>>> b = 2
>>> a + b
3
>>> a
1

Were you expecting a == 3?

Armin

unread,
Sep 16, 2008, 8:23:25 AM9/16/08
to
Alex Marandon wrote:
> Armin wrote:
>> Duncan Booth wrote:
>>
>> The semantic of [1,2,3,4,7].append(c) and [1,2,3,4,7] + c
>> (with c = [8,9]) is identical,
>
> No it's not, + doesn't alter its operands.
>
> >>> a = 1
> >>> b = 2
> >>> a + b
> 3

That's not the point :)

What's the value of 1.add(b)? None? Or 3 ??
(if add works in the same way as append)
a + b doesn't change a,b ... but a.add(b) -> a=3

Hrvoje Niksic

unread,
Sep 16, 2008, 8:22:19 AM9/16/08
to
Armin <a...@nospam.org> writes:

> What's the value of 1.add(b)? None? Or 3 ??
> (if add works in the same way as append)

That's exactly the point -- __add__ doesn't work as append. append is
a "destructive" operation, that mutates an existing object, whereas
__add__ returns a different object to be used as the "result" of the
addition. This is why append doesn't need to return anything, while
__add__ must return the new object.

The distinction is even more apparent with sort and sorted, which are
destructive and non-destructive aspects of the same operation:

>>> a = [3, 2, 1]
>>> a.sort() # destructive (mutates object), so no return value
>>> a
[1, 2, 3]

>>> a = [3, 2, 1]
>>> b = sorted(a) # non-destructive (sorts a copy), returns the sorted copy
>>> a
[3, 2, 1]
>>> b
[1, 2, 3]

Maric Michaud

unread,
Sep 16, 2008, 8:48:16 AM9/16/08
to pytho...@python.org
Le Tuesday 16 September 2008 14:23:25 Armin, vous avez écrit :
> Alex Marandon wrote:
> > Armin wrote:
> >> Duncan Booth wrote:
> >>
> >> The semantic of [1,2,3,4,7].append(c) and [1,2,3,4,7] + c
> >> (with c = [8,9]) is identical,
> >
> > No it's not, + doesn't alter its operands.
> >
> > >>> a = 1
> > >>> b = 2
> > >>> a + b
> >
> > 3
>
> That's not the point :)

It is, please try to understand it, in python all expressions that mutate an
object should return None, it's the case for

l.append(x)
l.sort()
l.reverse()

...

all expressions that return something, return a new object, it's the case for

1+2
1.__add__(2) (which is the same)
sorted(l)
l[i:j]
etc...


there are some noticeable exceptions :

For coding facilities, some APIs could return the modified part of the object,
ex : it = c.pop()

Returning the modifyied object itself is mostly considered bad style, because
it doesn't make clear if this the object or a copy. There is OTHO a use case
for this, for APIs that allow chaining of operations (don't find by memory
any example in stdlib, though), alike the ">>" operator in C++, but pyparsing
is a good example if I remember well. BTW, Pythoneers are not very fond of
that.

Finally, the very special case of augmented assignment operators :
x.__iadd__(y) which actually return the modified object, but this expression
isn't intended to be use by callers, refer to the manual to see a good
example of this, how one should implement __add__ and __iadd__ methods.

a += b
a = a + b

both are statments (doesn't evaluate to any object), but are not equivalent if
a is mutable.

>
> What's the value of 1.add(b)? None? Or 3 ??
> (if add works in the same way as append)
> a + b doesn't change a,b ... but a.add(b) -> a=3

> --
> http://mail.python.org/mailman/listinfo/python-list

--
_____________

Maric Michaud

Armin

unread,
Sep 16, 2008, 9:12:27 AM9/16/08
to
Maric Michaud wrote:
> Le Tuesday 16 September 2008 14:23:25 Armin, vous avez écrit :
>> Alex Marandon wrote:
>>> Armin wrote:
>>>> Duncan Booth wrote:
>>>>
>>>> The semantic of [1,2,3,4,7].append(c) and [1,2,3,4,7] + c
>>>> (with c = [8,9]) is identical,
>>> No it's not, + doesn't alter its operands.
>>>
>>> >>> a = 1
>>> >>> b = 2
>>> >>> a + b
>>>
>>> 3
>> That's not the point :)
>
> It is, please try to understand it, in python all expressions that mutate an
> object should return None, it's the case for
>
> l.append(x)
> l.sort()
> l.reverse()
>
> all expressions that return something, return a new object, it's the case for
>
> 1+2
> 1.__add__(2) (which is the same)
> sorted(l)
> l[i:j]
> etc...
>
> there are some noticeable exceptions :
>
> For coding facilities, some APIs could return the modified part of the object,
> ex : it = c.pop()
>
> Returning the modifyied object itself is mostly considered bad style, because
> it doesn't make clear if this the object or a copy.

OK ... That's a good point. Thanks !

--Armin

Grant Edwards

unread,
Sep 16, 2008, 9:47:04 AM9/16/08
to
On 2008-09-16, Armin <a...@nospam.org> wrote:
> John Machin wrote:
>> On Sep 16, 6:45 am, Armin <a...@nospam.org> wrote:
>>
>>> Yes, but this is very unconvenient.
>>> If d should reference the list a extended with a single list element
>>> you need at least two lines
>>>
>>> a.append(7)
>>> d=a
>>>
>>> and not more intuitive d = a.append(7)
>>
>> Methods/functions which return a value other than the formal None and
>> also mutate their environment are "a snare and a delusion". Don't wish
>> for them.
>
>
>
> c = [9,10]
> [1,2,3,4,7].append(c) -> Is this a valid expression?

Yes.

> The 'value' of that expression is None.

Correct.

> However ... that's the way of the implementation of the
> append method. It's a little bit confusing to me ...

No, that's a way of calling the append method of a list. The
fact that you don't have a name bound to that list doesn't
change the fact that the list is mutable and you appended
[9,10] to it.

--
Grant Edwards grante Yow! Are the STEWED PRUNES
at still in the HAIR DRYER?
visi.com

Grant Edwards

unread,
Sep 16, 2008, 9:49:48 AM9/16/08
to

It's also somewhat common to index into a literal:

['one','two','three'][n]

{1:'one', 2:'two', 7:'seven'}[n]

--
Grant Edwards grante Yow! I was born in a
at Hostess Cupcake factory
visi.com before the sexual
revolution!

Grant Edwards

unread,
Sep 16, 2008, 9:54:39 AM9/16/08
to
On 2008-09-16, Armin <a...@nospam.org> wrote:
> Duncan Booth wrote:
>> "Chris Rebert" <c...@rebertia.com> wrote:
>>> On Tue, Sep 16, 2008 at 1:20 AM, Armin <a...@nospam.org> wrote:
>>>> [1,2,3,4,7].append(c) -> Is this a valid expression?
>>> Literally, no, because you can't call methods on literals.
>>
>> Rubbish. There is no restriction about calling methods on literals. That
>> expression is perfectly valid but has no practical use that I can see.
>
> The semantic of [1,2,3,4,7].append(c) and [1,2,3,4,7] + c
> (with c = [8,9]) is identical,

No, they're not:

>>> a=[1,2,3,4,7]
>>> c=[9,10]
>>> a.append(c)
>>> a


[1, 2, 3, 4, 7, [9, 10]]


>>> a=[1,2,3,4,7]
>>> c=[9,10]
>>> a+c


[1, 2, 3, 4, 7, 9, 10]

You really ought to install a copy of Python so you can try out
things and see how they really work.

> but the first expression doesn't provide a value. Strange by
> design ...

Not really. You just need to make a little effort to
understand the reasoning (which has been explained to you)
behind Python's design decision.

--
Grant Edwards grante Yow! Somewhere in DOWNTOWN
at BURBANK a prostitute is
visi.com OVERCOOKING a LAMB CHOP!!

Grant Edwards

unread,
Sep 16, 2008, 9:55:56 AM9/16/08
to
On 2008-09-16, Armin <a...@nospam.org> wrote:
> Alex Marandon wrote:
>> Armin wrote:
>>> Duncan Booth wrote:
>>>
>>> The semantic of [1,2,3,4,7].append(c) and [1,2,3,4,7] + c
>>> (with c = [8,9]) is identical,
>>
>> No it's not, + doesn't alter its operands.
>>
>> >>> a = 1
>> >>> b = 2
>> >>> a + b
>> 3
>
> That's not the point :)
>
> What's the value of 1.add(b)? None? Or 3 ??

>>> a = 1
>>> b = 2

>>> 1.add(b)
File "<stdin>", line 1
1.add(b)
^
SyntaxError: invalid syntax

> (if add works in the same way as append)

It doesn't.

> a + b doesn't change a,b ... but a.add(b) -> a=3

WTH are you talking about?

--
Grant Edwards grante Yow! I just got my PRINCE
at bumper sticker ... But now
visi.com I can't remember WHO he
is ...

Grant Edwards

unread,
Sep 16, 2008, 9:57:53 AM9/16/08
to
On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:

> all expressions that return something, return a new object,

That's not _quite_ true:

>>> a=1
>>> b=a.__add__(0)
>>> a is b
True

;)

--
Grant Edwards grante Yow! LOOK!! Sullen
at American teens wearing
visi.com MADRAS shorts and "Flock of
Seagulls" HAIRCUTS!

Maric Michaud

unread,
Sep 16, 2008, 10:10:49 AM9/16/08
to pytho...@python.org
Le Tuesday 16 September 2008 15:57:53 Grant Edwards, vous avez écrit :
> On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:
> > all expressions that return something, return a new object,
>
> That's not _quite_ true:
> >>> a=1
> >>> b=a.__add__(0)
> >>> a is b
>
> True
>
> ;)

This is implementation specific, the specification of the language says that
it should be false, and it is for higher numbers :

>>>[15]: a=1000

>>>[16]: b=a.__add__(0)

>>>[17]: a is b
...[17]: False

Don't disturb our OP, with side questions, please, it was enough hard like
this ;)

--
_____________

Maric Michaud

Grant Edwards

unread,
Sep 16, 2008, 10:57:26 AM9/16/08
to
On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:
> Le Tuesday 16 September 2008 15:57:53 Grant Edwards, vous avez écrit :
>> On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:
>> > all expressions that return something, return a new object,
>>
>> That's not _quite_ true:
>> >>> a=1
>> >>> b=a.__add__(0)
>> >>> a is b
>>
>> True
>>
>> ;)
>
> This is implementation specific,

Indeed.

> the specification of the language says that it should be
> false,

That's curious. If so, then the implimentation is in violating
the specification. Where is that in the specification? I
suspect the statement in the specification should only apply to
mutable objects.

> and it is for higher numbers :
>
>>>>[15]: a=1000
>
>>>>[16]: b=a.__add__(0)
>
>>>>[17]: a is b
> ...[17]: False
>
> Don't disturb our OP, with side questions, please, it was
> enough hard like this ;)

I'm not trying to confuse the OP, but to quote Einstein:
"Everything should be made as simple as possible, but not
simpler."

--
Grant Edwards grante Yow! I wonder if I could
at ever get started in the
visi.com credit world?

Maric Michaud

unread,
Sep 16, 2008, 12:07:03 PM9/16/08
to pytho...@python.org
Le Tuesday 16 September 2008 16:57:26 Grant Edwards, vous avez écrit :
> On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:
> > Le Tuesday 16 September 2008 15:57:53 Grant Edwards, vous avez écrit :
> >> On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:
> >> > all expressions that return something, return a new object,
> >>
> >> That's not _quite_ true:
> >> >>> a=1
> >> >>> b=a.__add__(0)
> >> >>> a is b
> >>
> >> True
> >>
> >> ;)
> >
> > This is implementation specific,
>
> Indeed.
>
> > the specification of the language says that it should be
> > false,
>
> That's curious. If so, then the implimentation is in violating
> the specification.

But it doesn't matter as the "is" operator is not relevant for any use case
with scalars and even strings and the optimization is not negligible.
In fact, I'd rather say it's unspecified, each implementation does it its own
way.

maric@redflag1 17:48:03:~$ ipython

>>>[1]: int() is 0 # contructor honour cache
...[1]: True

>>>[2]: 256 is 255+1 # still caching
...[1]: True

>>>[3]: 257 is 255+2 # here it stops
...[3]: False

maric@redflag1 17:48:08:~$ jython
Jython 2.2.1 on java1.6.0_07
Type "copyright", "credits" or "license" for more information.
>>> int() is 0 # not caching when using constructor
0
>>> 2 is 1+1 # caching on expression
1
>>> 500 is 250*2 # caching occurs beyond my CPython
1
>>> 5000 is 5000 # compile-time optimization
1
>>> 5000 is 2500*2 # not caching too big numbers
0


> Where is that in the specification?

Each literal creates a new instance, and instances of int are not supposed to
be unique for each value (at less it's not specified so), so "1 is not 1",
but implementation can cache integers, short strings, to avoid creating an
new instance each time they appear in code.

jython do this also for integer (see above), but not for strings :

maric@redflag1 17:33:52:~$ jython
Jython 2.2.1 on java1.6.0_07
Type "copyright", "credits" or "license" for more information.
>>> a = "aaaa"
>>> a is "aaaa"
0
maric@redflag1 17:36:48:~$ ipython

>>>[1]: a = "aaaa"

>>>[2]: a is "aaaa"
...[2]: True

BTW, I'm talking of Jython 2.2, Jython 2.4, which quite ready I think, can
change his mind as well.

> I
> suspect the statement in the specification should only apply to
> mutable objects.
>

No, CPython also have a unique empty tuple, but tuple literals are not cached
nor there are compile-time optimization :

>>>[5]: () is ()
...[5]: True

>>>[6]: (1,) is (1,)
...[6]: False


> > and it is for higher numbers :
> >>>>[15]: a=1000
> >>>>
> >>>>[16]: b=a.__add__(0)
> >>>>
> >>>>[17]: a is b
> >
> > ...[17]: False
> >
> > Don't disturb our OP, with side questions, please, it was
> > enough hard like this ;)
>
> I'm not trying to confuse the OP, but to quote Einstein:
> "Everything should be made as simple as possible, but not
> simpler."

--
_____________

Maric Michaud

Grant Edwards

unread,
Sep 16, 2008, 12:26:38 PM9/16/08
to
On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:
> Le Tuesday 16 September 2008 16:57:26 Grant Edwards, vous avez écrit :
>> On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:
>> > Le Tuesday 16 September 2008 15:57:53 Grant Edwards, vous avez écrit :
>> >> On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:
>> >>
>> >> > all expressions that return something, return a new object,
>> >>
>> >> That's not _quite_ true:
>> >> >>> a=1
>> >> >>> b=a.__add__(0)
>> >> >>> a is b
>> >>
>> >> True
>> >>
>> >> ;)
>> >
>> > This is implementation specific,
>>
>> Indeed.
>>
>> > the specification of the language says that it should be
>> > false,
>>
>> That's curious. If so, then the implimentation is in violating
>> the specification.
>
> But it doesn't matter

No argument.

> as the "is" operator is not relevant for any use case with
> scalars and even strings and the optimization is not
> negligible. In fact, I'd rather say it's unspecified, each
> implementation does it its own way.

I was just pointing out that for some degenerate cases in the
C-Python implementation, the statement "all expressions that
return something, return a new object" is not true. I'm not
saying it ought to be true. I'm just saying that if the
specification says that, it's a bug (in the specification,
IMO).

If the specification states that, then either the specification
should be changed, or the implementation should be changed.
Waving away specification violations with claims of "it doesn't
matter" just seems like bad practice. If a requirement doesn't
matter, then remove it from the specification.

>> Where is that in the specification?
>
> Each literal creates a new instance, and instances of int are
> not supposed to be unique for each value (at less it's not
> specified so), so "1 is not 1", but implementation can cache
> integers, short strings, to avoid creating an new instance
> each time they appear in code.

Quite true, but that's not what I was asking.

I was asking where in the specification <http://docs.python.org/ref/ref.html>
it says that all expressions that return something, return a
new object.

> jython do this also for integer (see above), but not for strings :
>
> maric@redflag1 17:33:52:~$ jython
> Jython 2.2.1 on java1.6.0_07
> Type "copyright", "credits" or "license" for more information.
>>>> a = "aaaa"
>>>> a is "aaaa"
> 0
> maric@redflag1 17:36:48:~$ ipython
>
>>>>[1]: a = "aaaa"
>
>>>>[2]: a is "aaaa"
> ...[2]: True
>
> BTW, I'm talking of Jython 2.2, Jython 2.4, which quite ready I think, can
> change his mind as well.
>
>> I suspect the statement in the specification should only apply
>> to mutable objects.
>
> No, CPython also have a unique empty tuple, but tuple literals
> are not cached nor there are compile-time optimization :

I don't see how that's material. My suggestion was that the
requirement of "returning a new object" only apply to mutable
objects, since it's clearly not true for some immutable objects
[nor would there be any benefit for it to be so].

The behavior with immutable objects (integers and tuples) is
then irrelevent.

--
Grant Edwards grante Yow! I didn't order any
at WOO-WOO ... Maybe a YUBBA
visi.com ... But no WOO-WOO!

Maric Michaud

unread,
Sep 16, 2008, 12:47:02 PM9/16/08
to pytho...@python.org
Le Tuesday 16 September 2008 18:26:38 Grant Edwards, vous avez écrit :
> I was asking where in the specification
> <http://docs.python.org/ref/ref.html> it says that all expressions that
> return something, return a
> new object.  

I never said this, I said it's the spirit of python APIs, with some noticeable
exceptions (see my first post).
But for this case specifically, a + b *should* return a new object, see the
documentation of __add__ and __iadd__ special methods, it's clearly stated.

The fact that an integer with value "1" is always the same integer in some
implementation is unrelated to the original problem.

--
_____________

Maric Michaud

Grant Edwards

unread,
Sep 16, 2008, 12:56:53 PM9/16/08
to
On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:
> Le Tuesday 16 September 2008 18:26:38 Grant Edwards, vous avez écrit :
>> I was asking where in the specification
>> <http://docs.python.org/ref/ref.html> it says that all expressions that
>> return something, return a
>> new object.  
>
> I never said this,

Here's what you wrote:

>>>> all expressions that return something, return a new object.
>>

>>> That's not _quite_ true:
>>> >>> a=1
>>> >>> b=a.__add__(0)
>>> >>> a is b
>>>
>>> True
>>

>>This is implementation specific, the specification of the


>>language says that it should be false,

You made a statement, I pointed out a degenerate case where
that statement was violated. You replied that that my
counter-example violated the language specification. I read
that as a claim that your original statement was part of the
language specification.

If that's not what you meant, I aplogize. I'll should have
been more specific and asked "in the counter example above,
where in the laguage specification does it shat that 'a is b'
is supopsed to be false?"

> I said it's the spirit of python APIs, with some noticeable
> exceptions (see my first post). But for this case
> specifically, a + b *should* return a new object, see the
> documentation of __add__ and __iadd__ special methods, it's
> clearly stated.

I'll take a look...

> The fact that an integer with value "1" is always the same
> integer in some implementation is unrelated to the original
> problem.

Not if it results in a violation of something in the language
specification.

--
Grant Edwards grante Yow! Pardon me, but do you
at know what it means to be
visi.com TRULY ONE with your BOOTH!

Terry Reedy

unread,
Sep 16, 2008, 1:06:35 PM9/16/08
to pytho...@python.org
Maric Michaud wrote:

> It is, please try to understand it, in python all expressions that mutate an
> object should return None,

You are over-generalizing. For builtin classes, mutation methods return
none. Guido recommends this as a general practice, but users may do
whatever they like in their own classes. In fact, people have been told
that if they do not like the built-in behavior, they should make their
own, possibly by subclassing.

For augmented assignment, in-place mutation followed by rebinding is
explictly allowed and done for lists.

> all expressions that return something, return a new object

Nonesense. There is nothing in the ref manual that says this and parts
that say otherwise.

> there are some noticeable exceptions :

They are only exceptions to your rule, not to the language specification.

Terry Reedy

unread,
Sep 16, 2008, 1:31:40 PM9/16/08
to pytho...@python.org
Maric Michaud wrote:

> Le Tuesday 16 September 2008 15:57:53 Grant Edwards, vous avez écrit :
>> On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:
>>> all expressions that return something, return a new object,
>> That's not _quite_ true:
>>>>> a=1
>>>>> b=a.__add__(0)
>>>>> a is b
>> True
>>
>> ;)
>
> This is implementation specific, the specification of the language says that
> it should be false,

Please quote the section of the manual that says this.

> and it is for higher numbers :

Agaiin, this is implementation specific. An implementation would be
free to special-case any or all of +a, a+0, a-0, a*1, a//1, a**1, a<<0,
a>>0, and a|0 and return a. That CPython only optimizes the first is a
judgment that the other cases are too rare to bother with.

> Don't disturb our OP, with side questions, please, it was enough
hard like
> this ;)

Stop peddling false information. For immutable objects, identity is
irrelevant except for id and is.

tjr


Terry Reedy

unread,
Sep 16, 2008, 1:41:11 PM9/16/08
to pytho...@python.org
Maric Michaud wrote:

> Le Tuesday 16 September 2008 16:57:26 Grant Edwards, vous avez écrit :

>> Where is that in the specification?

> Each literal creates a new instance,

This does not answer 'where' but just adds another false claim. I just
reread the Reference Manual, Lexical Analysis chapter, Literals section
and there is nothing like that that I saw. And the reference
implementation is obviously different.

Grant Edwards

unread,
Sep 16, 2008, 1:43:29 PM9/16/08
to
On 2008-09-16, Maric Michaud <ma...@aristote.info> wrote:
> Le Tuesday 16 September 2008 18:26:38 Grant Edwards, vous avez ?crit?:

>> I was asking where in the specification
>> <http://docs.python.org/ref/ref.html> it says that all

>> expressions that return something, return a new object. ?


>
> I never said this, I said it's the spirit of python APIs, with
> some noticeable exceptions (see my first post). But for this
> case specifically, a + b *should* return a new object, see the
> documentation of __add__ and __iadd__ special methods, it's
> clearly stated.

OK, I've read through the documentation for __add__ and
__iadd__ in the language reference, and I can't find anything
that states or implies that they are to return a new object.

Can you perhaps provide a link or some sort of cite?

--
Grant Edwards grante Yow! Are you selling NYLON
at OIL WELLS?? If so, we can
visi.com use TWO DOZEN!!

J. Cliff Dyer

unread,
Sep 16, 2008, 3:07:57 PM9/16/08
to Grant Edwards, pytho...@python.org

On Tue, 2008-09-16 at 08:49 -0500, Grant Edwards wrote:
> On 2008-09-16, Hrvoje Niksic <hni...@xemacs.org> wrote:
> > Duncan Booth <duncan...@invalid.invalid> writes:
> >
> >> The only relatively common use I can think of where you might want to call
> >> a method directly on a literal is to produce a list of strings while being
> >> lazy about the typing:
> >
> > By far the most common is probably 'sep'.join(iterable).
>
> It's also somewhat common to index into a literal:
>
> ['one','two','three'][n]
>
> {1:'one', 2:'two', 7:'seven'}[n]
>

Indeed. I use this for setting variables based on hostname on a
website. Say, for example, you run on port 80 on one host, but on a
test host, you share with several other sites, and run on 8084, you can
do the following

import socket

port = {
'www.example.com': 80,
'dev.example.com': 8084,
}[socket.gethostname()]

It's a handy idiom.

Cheers,
Cliff


Lie

unread,
Sep 17, 2008, 11:51:08 AM9/17/08
to
On Sep 16, 3:20 pm, Armin <a...@nospam.org> wrote:
> John Machin wrote:
> > On Sep 16, 6:45 am, Armin <a...@nospam.org> wrote:
>
> >> Yes, but this is very unconvenient.
> >> If d should reference the list a extended with a single list element
> >> you need at least two lines
>
> >> a.append(7)
> >> d=a
>
> >> and not more intuitive d = a.append(7)
>
> > Methods/functions which return a value other than the formal None and
> > also mutate their environment are "a snare and a delusion". Don't wish
> > for them.
>
>    c = [9,10]
>    [1,2,3,4,7].append(c) -> Is this a valid expression?
>

Yes, that is a valid expression, however, the list you're appending to
is immediately discarded.

>    The 'value' of that expression is None.
>

>    However ... that's the way of the implementation of the append method.
>    It's a little bit confusing to me ...

actually, you could implement your own myList which returns a value on
append method:

class MyList(list):
def append(self, item):
list.append(self, item)
return self
# or
# return self[:]
# if you want it to return a copy

But I recommend against that.

> --Armin
>
> Thanks to all !
>
>
>
>
>
> > Inconvenient? How often do you want to mutate a list and then set up
> > another reference to it?- Hide quoted text -
>
> - Show quoted text -

Steve Holden

unread,
Sep 18, 2008, 1:01:55 PM9/18/08
to pytho...@python.org
tony.c...@googlemail.com wrote:
> On Sep 16, 6:03 am, Peter Anderson <peter.ander...@internode.on.net>
> wrote:
>> "/... I don't think you've thought this one through, really./"
>> snip
>>
>> We ought to try and be a little kinder to others on the list, don't you
>> think? :-)
>>
>> snip
>
> Well said!

>From personal experience I find that honest attempts to straighten
people out lead to accusations of exploiting "seniority" to attack people.

There goes the neighborhood, I guess.

Of course we should try to maintain c.l.py's deserved reputation for
civil behavior, but things like that aren't easy to police.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Steve Holden

unread,
Sep 18, 2008, 1:19:49 PM9/18/08
to pytho...@python.org
Armin wrote:
> Duncan Booth wrote:
>> "Chris Rebert" <c...@rebertia.com> wrote:
>>> On Tue, Sep 16, 2008 at 1:20 AM, Armin <a...@nospam.org> wrote:
>>>> [1,2,3,4,7].append(c) -> Is this a valid expression?
>>> Literally, no, because you can't call methods on literals.
>>
>> Rubbish. There is no restriction about calling methods on literals.
>> That expression is perfectly valid but has no practical use that I can
>> see.
>
> The semantic of [1,2,3,4,7].append(c) and [1,2,3,4,7] + c
> (with c = [8,9]) is identical, but the first expression doesn't provide
> a value. Strange by design ...
>
Have a care, there. The semantics are different.

lst = [1, 2, 3, 4, 7]
lst.append([8, 9])

makes lst

[1, 2, 3, 4, 7, [8, 9]]

whereas

lst = [1, 2, 3, 4, 7]
lst = lst + [8, 9]

makes lst

[1, 2, 3, 4, 5, 7, 8, 9]

I suspect you meant [1, 2, 3, 4, 5, 7] + [c]

0 new messages