增加int对象

时间:2009-07-16 04:06:13

标签: python int

python中有没有办法增加int对象,int似乎没有实现__iadd__所以+ = 1实际上返回一个新对象

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

我想要的是保持指向同一个物体。

目的:我有从int派生的类,我想为该类实现C类型'++ n'运算符

结论:好的,因为int是不可变的,没有办法,看起来我将不得不写自己的类这样的东西

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

7 个答案:

答案 0 :(得分:12)

int是不可变的,所以如果你想要一个“mutable int”,你必须使用所有int的方法构建自己的类

答案 1 :(得分:5)

如果你必须让代码工作,这里是一个脏方法,其中一个实例方法向上移动一个帧并覆盖它自己的本地条目。不建议。 (比如,真的没有。我甚至不确定那是做什么的。旧实例会发生什么?我对框架知之甚少......)。真的,我只是张贴这个,因为每个人都说这是不可能的,而实际上它只是荒谬可笑的形式。 ; - )

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,

输出:

9 8 7 6 5 4 3 2 1

答案 2 :(得分:5)

您可以将ctypes用作可变整数。选择正确的ctype非常重要,因为它们限制了它们可以携带的整数大小。

>>> from ctypes import c_int64
>>> num = c_int64(0)
>>> id(num)
4447709232
>>> def increment(number):
...     number.value += 1
... 
>>> increment(num)
>>> increment(num)
>>> increment(num)
>>> num.value
3
>>> id(num)
4447709232
>>> 

更多信息:https://docs.python.org/2/library/ctypes.html#fundamental-data-types

答案 3 :(得分:3)

创建一个实现int方法并包装内部整数的类可能会更容易。

答案 4 :(得分:3)

您可以将一个不可变对象放在一个可变容器中;列表最简单。

此代码打印0,证明问题:

a = 0       # `a` points to a new int (a `0`)
b = a       # `b` points to the same thing as `a` (the `0`)
b = 1       # `b` points to a new int (a `1`)
print(a)    # `a` still points to the same thing (the `0`)

如果你把int放在一个列表中,但是使用与以前相同的代码,你可以得到一个mutable int的效果(尽管它是真正被变异的列表):

a = [0]        # `a` points to a new `0` inside a new list
b = a          # `b` points to the same thing as `a` (the list)
b[0] = 1       # the list that `a` and `b` point to is mutated
print(a[0])    # `a[0]` points to the same object as `b[0]` (the `1`)

在实践中,您应该构建数据,以便上述“技巧”是多余的。这些示例不应该直接使用,而应该帮助您弄清楚该怎么做。

答案 5 :(得分:0)

是的,简短的回答是,整数是不可改变的。

答案 6 :(得分:0)

我今天遇到了类似的问题,并提出了一个名为IterInt的类,它允许您使用“+”和“ - ”装饰器增加或减少位置。

用法:

x = IterInt()

print x
# result: 0

print +x
# result: 1

print +x
# result: 2

print +x
# result: 3

print -x
# result: 2

print -x
# result: 1

print -x
# result: 0

在我的情况下,我想要通过在特定索引之后插入几个命令项来修改应用程序的现有菜单。我正在使用的API提供了一个“addCommand”函数,可以获取要插入的索引。

考虑这个伪代码,其中菜单有命令a到g,比如menu = [a,f,g],我想在索引1-4插入b-e

idx = 1
menu.addCommand(b, index=idx)
idx += 1
menu.addCommand(c, index=idx)
idx += 1
menu.addCommand(d, index=idx)
idx += 1
menu.addCommand(e, index=idx)
idx += 1

# result: menu = [a, b, c, d, e, f]

如果我可以编写它会很好,所以idx会增加到c,我可以做idx ++,但函数不允许python的idx + = 1方法论。

解决方案:

class IterInt(int):
"""
This function will return the next integer from the init_value starting point or 0 if None.
Each subsequent call to increment returns the next value
:param init_value:
:return:
"""
def __init__(self, init_value=None):
    if init_value is None:
        init_value = 0

    if init_value is not None:
        self.increment_value = init_value
    self.increment_value = init_value

def __pos__(self):
    self.increment_value += 1
    return self.increment_value

def __neg__(self):
    self.increment_value -= 1
    return self.increment_value


idx = IterInt(1)
menu.addCommand(b, index=+idx)
menu.addCommand(c, index=+idx)
menu.addCommand(d, index=+idx)
menu.addCommand(e, index=+idx)

# result: menu = [a, b, c, d, e, f]