append on lists

M

Maric Michaud

Le Tuesday 16 September 2008 14:23:25 Armin, vous avez écrit :
Alex said:
Armin said:
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.
 
A

Armin

Maric said:
Le Tuesday 16 September 2008 14:23:25 Armin, vous avez écrit :
Alex said:
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
 
M

Maric Michaud

Le Tuesday 16 September 2008 15:57:53 Grant Edwards, vous avez écrit :
That's not _quite_ true:

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

Maric Michaud

Le Tuesday 16 September 2008 16:57:26 Grant Edwards, vous avez écrit :
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.
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.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]: True
...[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."
 
M

Maric Michaud

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.
 
T

Terry Reedy

Maric said:
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.
 
T

Terry Reedy

Maric said:
Le Tuesday 16 September 2008 15:57:53 Grant Edwards, vous avez écrit :

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
 
T

Terry Reedy

Maric said:
Le Tuesday 16 September 2008 16:57:26 Grant Edwards, vous avez écrit :
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.
 
J

J. Cliff Dyer

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
 
L

Lie

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.
 
S

Steve Holden

Armin said:
Duncan said:
Chris Rebert said:
[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]

regards
Steve
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,274
Latest member
JessMcMast

Latest Threads

Top