tags:

views:

428

answers:

5

Is there a way in python to increment int object in place, int doesn't seem to implement __iadd__ so += 1 actually returns a new object

>>> n=1
>>> id(n)
9788024
>>> n+=1
>>> id(n)
9788012

What I want is n to remain pointing to same object.

Purpose: I have class derived from int and I want to implement C type '++n' operator for that class

Conclusion: ok as int is immutable there is no way, looks like i will have to write my own class something like this

class Int(object):
    def __init__(self, value):
        self._decr = False
        self.value = value

    def __neg__(self):
        if self._decr:
            self.value -= 1
        self._decr = not self._decr
        return self

    def __str__(self):
        return str(self.value)

    def __cmp__(self, n):
        return cmp(self.value, n)

    def __nonzero__(self):
        return self.value

n = Int(10)
while --n:
    print n
+3  A: 

It would probably be easier to create a class that implements the int methods and wraps an internal integer.

Ryan
Not just easier, but may be the only way as ints are not mutable
scrible
A: 

Use another layer of indirection.

wrang-wrang
+7  A: 

ints are immutable, so you'll have to build your own class with all the int's methods if you want a "mutable int"

scrible
The ints in that class will still be immutable.
Seun Osewa
A: 

Hah, seems I misread the op.

But yes, the short answer is that, ints are immutable.

Fake Code Monkey Rashid
+1  A: 

If you absolutely have to get that code to work, here's a dirty method, where an instance method moves up a frame and overwrites its own locals entry. Wouldn't recommend. (like, really not. I'm not even sure what that does. What happens to the old instance? I don't know enough about frames...). Really, I'm only posting this because everyone said it's impossible, when in reality it's just ridiculously bad form. ;-)

import sys
class FakeInt(int):
    def __init__(self, *arg, **kwarg):
        self._decr = False
        int.__init__(self, *arg, **kwarg)
    def __neg__(self):
        if self._decr:

            upLocals = sys._getframe(1).f_locals
            keys, values = zip(*upLocals.items())
            i = list(values).index(self)

            result = FakeInt(self-1)
            upLocals[keys[i]]=result

            return result
        self._decr = not self._decr
        return self

A = FakeInt(10)
while --A:
    print A,

outputs:

9 8 7 6 5 4 3 2 1
Markus
on an unrelated note, does anyone know if it's possible to find the index of an item in a tuple without converting it to a list first? i = list(values).index(self) seems a bit roundabout.
Markus
+1 interesting, but yes I would be scared to use this
Anurag Uniyal