# Is behavior of += intentional for int?

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Wed Sep 2 05:48:43 CEST 2009

```On Tue, 01 Sep 2009 16:43:06 -0700, Carl Banks wrote:

>> Numbers are immutable by nature (math). The number 3.14 remains 3.14
>> whatever you try to do with it. What you call an immutable number is in
>> fact a container that contains a number.
>
> I wouldn't agree with that terminology or logic.

Abstract numbers aren't really "things", they're concepts, and as such I
don't think mutable or immutable has any meaning. But if it does, then
abstract numbers are immutable, because you can't change one into two
without losing the value one, and that certainly doesn't happen.

> First of all "mutable number" is really just a short way to say "mutable
> number object".

Yes, but "object" in the above doesn't necessarily mean object in the
sense of object-oriented programming. Perhaps a better word is "mutable
number thing", where "thing" could be an object in the OOP sense, or a
variable in the memory-location sense, or on a stack, in a register, or
chalk marks on a whiteboard.

> A number object in Python is not a number, it's just a
> representation of a number. Even if numbers are immutable by nature, an
> object representing a number need not be.

/s/number/abstract number/

Given that, then I agree, but given Python's implementation, you would
need more than one change to make number's mutable, and what you would
have wouldn't be Python any more.

> And if your number object is mutable, it does not make that object a
> container, at least not what I would call a container.  A container you
> have to dereference somehow to get at the object inside, whereas a
> mutable number object you don't dereference: it acts like number as- is.

Agreed, so long as we're talking from the programmer's perspective. From
the compiler's perspective, or the Virtual Machine's perspective,
variables of the type "value stored at memory location" are a kind of
container: you don't dereference anything, but the compiler does.

There are multiple perspectives which are valid at once, depending on
where you're looking from. A *name* is kind of a container (but not in
the same sense that lists and dicts are containers), in that the VM has
to dereference the name to get to the object.

> IOW, the first example below is a container, the second is not:

Do you mean the name `num` is a container, or the *contents* of `num` is
a container? I assume you mean the contents.

> num = [2]
> num[0] += 3
>
> num = mutable_int(2)
> num += 3

In the sense of container that you give, I agree. But there's nothing
magic about mutable_int() in the above -- num could be bound to a regular
int, and it still wouldn't be a container. Obviously.

> (If you want to call the mutable number a container anyway, fine with
> me, I am not here to bicker.)  A container is sufficient to get a layer
> of indirection if that's what you want the mutable number for.
>
> However, the mutable number has a performance advantage over using a
> container: it avoids the overhead of creating a new object.

You're assuming that the overhead of flipping bits is less than the
overhead of creating a new object, and that's almost certainly valid if
the VM is implemented in (say) C. But it may not be the case if the VM is
implemented in (say) Python, or Javascript, in which case "create a new
object" might be less expensive than "flip a bunch of bits". If you can
get the CPU to flip your bits, that will be fast, but perhaps your
implementation needs to convert the int to a string of ones and zeroes,
then perform bit-operations on those, then convert back to a real int.

(I mention this as a theoretical issue, not a serious objection to the
existing CPython implementation. But perhaps the PyPy people have to deal
with it?)

--
Steven

```