in place functions from operator module

E

ernest

Hi,

The operator module provides separate functions for
"in place" operations, such as iadd(), isub(), etc.
However, it appears that these functions don't really
do the operation in place:

In [34]: a = 4

In [35]: operator.iadd(a, 3)
Out[35]: 7

In [36]: a
Out[36]: 4

So, what's the point? If you have to make the
assignment yourself... I don't understand.

Cheers,
Ernest
 
P

Peter Otten

ernest said:
The operator module provides separate functions for
"in place" operations, such as iadd(), isub(), etc.
However, it appears that these functions don't really
do the operation in place:

In [34]: a = 4

In [35]: operator.iadd(a, 3)
Out[35]: 7

In [36]: a
Out[36]: 4

So, what's the point? If you have to make the
assignment yourself... I don't understand.

Integers are immutable, and for instances a of immutable types

a += b

is equivalent to

a = a + b

For mutable types like list add() and iadd() differ:
a = ["first"]
operator.iadd(a, [42]) ['first', 42]
a
['first', 42]
a = ["first"]
operator.add(a, [42]) ['first', 42]
a
['first']

Peter
 
P

Peter Otten

ernest said:
The operator module provides separate functions for
"in place" operations, such as iadd(), isub(), etc.
However, it appears that these functions don't really
do the operation in place:

In [34]: a = 4

In [35]: operator.iadd(a, 3)
Out[35]: 7

In [36]: a
Out[36]: 4

So, what's the point? If you have to make the
assignment yourself... I don't understand.

Integers are immutable, and for instances a of immutable types

a += b

is equivalent to

a = a + b

For mutable types like list add() and iadd() may differ:
a = ["first"]
operator.iadd(a, [42]) ['first', 42]
a
['first', 42]
a = ["first"]
operator.add(a, [42]) ['first', 42]
a
['first']

Peter
 
E

ernest

ernest said:
The operator module provides separate functions for
"in place" operations, such as iadd(), isub(), etc.
However, it appears that these functions don't really
do the operation in place:
In [34]: a = 4
In [35]: operator.iadd(a, 3)
Out[35]: 7
In [36]: a
Out[36]: 4
So, what's the point? If you have to make the
assignment yourself... I don't understand.

Integers are immutable, and for instances a of immutable types

a += b

is equivalent to

a = a + b

For mutable types like list add() and iadd() may differ:
a = ["first"]
operator.iadd(a, [42]) ['first', 42]
a

['first', 42]
a = ["first"]
operator.add(a, [42]) ['first', 42]
a

['first']

It makes sense now. Thank you :)

Ernest
 
A

Arnaud Delobelle

ernest said:
Hi,

The operator module provides separate functions for
"in place" operations, such as iadd(), isub(), etc.
However, it appears that these functions don't really
do the operation in place:

In [34]: a = 4

In [35]: operator.iadd(a, 3)
Out[35]: 7

In [36]: a
Out[36]: 4

So, what's the point? If you have to make the
assignment yourself... I don't understand.

Cheers,
Ernest

That's because

a += b

is executed as:

a = a.__iadd__(b)

For immutable objects, (such as integers), a.__iadd__(b) returns a + b
*and then* this value is assigned to a (or rather 'a' is bound to the
value). So for immutables objects, iadd(a, b) is the same as a + b

For mutable objects (such as lists), a.__iadd__(b) mutates the object
*and then* returns self so that when the assignement is executed, 'a'
will still be bound the the same object. E.g. if a = [1, 2] then

a += [3]

will first append 3 to the list and then reassign the list to 'a' (it is
unnecessary in this case but if this step was omitted, the "in place"
operators wouldn't work on immutables types).
 
S

Steven D'Aprano

Hi,

The operator module provides separate functions for "in place"
operations, such as iadd(), isub(), etc. However, it appears that these
functions don't really do the operation in place:

In [34]: a = 4

In [35]: operator.iadd(a, 3)
Out[35]: 7

In [36]: a
Out[36]: 4

So, what's the point? If you have to make the assignment yourself... I
don't understand.


The point is that if you could modify the int 4 to become 7, you would
then see horrible things like this:

8

Nobody wants that. Some very early versions of Fortran allowed that sort
of thing, apparently by accident. I've been told you can get it to work
with Lisp too, and Python with ctypes. You don't want to go there.

That is why ints are immutable in Python, and so "in-place" operations
aren't really in-place for them.

Remember that 4 is an actual *object*, and so the iadd function can only
see the object, not the name it is bound to. It sees 4 as the first
argument, not the memory location of "a". There's no way for it to know
which name you are trying to modify, or even if the object 4 is bound to
any name.
 
R

Raymond Hettinger

ernest said:
The operator module provides separate functions for
"in place" operations, such as iadd(), isub(), etc.
However, it appears that these functions don't really
do the operation in place:
In [34]: a = 4
In [35]: operator.iadd(a, 3)
Out[35]: 7
In [36]: a
Out[36]: 4
So, what's the point? If you have to make the
assignment yourself... I don't understand.
Cheers,
Ernest

That's because

   a += b

is executed as:

   a = a.__iadd__(b)

For immutable objects, (such as integers), a.__iadd__(b) returns a + b
*and then* this value is assigned to a (or rather 'a' is bound to the
value).  So for immutables objects, iadd(a, b) is the same as a + b

For mutable objects (such as lists), a.__iadd__(b) mutates the object
*and then* returns self so that when the assignement is executed, 'a'
will still be bound the the same object.  E.g. if a = [1, 2] then

    a += [3]

will first append 3 to the list and then reassign the list to 'a' (it is
unnecessary in this case but if this step was omitted, the "in place"
operators wouldn't work on immutables types).

This is an excellent explanation.
Perhaps, you can submit a documentation
patch for the operator module so this
doesn't get lost.


Raymond
 
A

Arnaud Delobelle

Raymond Hettinger said:
ernest said:
The operator module provides separate functions for
"in place" operations, such as iadd(), isub(), etc.
However, it appears that these functions don't really
do the operation in place:
In [34]: a = 4
In [35]: operator.iadd(a, 3)
Out[35]: 7
In [36]: a
Out[36]: 4
So, what's the point? If you have to make the
assignment yourself... I don't understand.
Cheers,
Ernest

That's because

   a += b

is executed as:

   a = a.__iadd__(b)

For immutable objects, (such as integers), a.__iadd__(b) returns a + b
*and then* this value is assigned to a (or rather 'a' is bound to the
value).  So for immutables objects, iadd(a, b) is the same as a + b

For mutable objects (such as lists), a.__iadd__(b) mutates the object
*and then* returns self so that when the assignement is executed, 'a'
will still be bound the the same object.  E.g. if a = [1, 2] then

    a += [3]

will first append 3 to the list and then reassign the list to 'a' (it is
unnecessary in this case but if this step was omitted, the "in place"
operators wouldn't work on immutables types).

This is an excellent explanation.
Perhaps, you can submit a documentation
patch for the operator module so this
doesn't get lost.


Raymond

I have submitted a documentation patch:

http://bugs.python.org/issue9717
 

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

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,147
Latest member
CarenSchni
Top