2009-07-16 55 views
14

是否有蟒蛇的方式来增加到位int对象,诠释似乎并没有实现__iadd__所以+ = 1实际上返回一个新的对象增量int对象

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

我想为n保持指向同一个对象。

目的:我从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 
+0

为什么你想实现一个前缀操作呢?你打算添加一个自定义预处理器来将++ n转换为方法调用吗? – Ryan 2009-07-16 04:11:10

+1

嗯我只想显示我的朋友python可以做--n:打印n;) – 2009-07-16 04:24:04

+0

看到这一个很好,如果稍微复杂的方式来包装你的ints在一个匿名类(这是可变的),它将表现得像一个'reference':http://stackoverflow.com/a/1123054/409638 ie ref = type('',(),{'n':1}) – robert 2014-11-06 11:58:33

回答

12

整型是不变的,所以你必须与所有整型的方法来建立自己的类,如果你想有一个“可变INT”

+5

该类中的整数仍然是不变的。 – 2009-07-16 11:22:11

3

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

+1

不仅更简单,而且可能是唯一的方法,因为整数不可变 – Arkady 2009-07-16 04:12:22

0

是,简单的答案是,整数是不可改变的。

3

如果你绝对必须让代码工作,这里有一个肮脏的方法,其中一个实例方法向上移动一个框架并覆盖它自己的本地条目。不会推荐。 (比如,真的不是,我甚至不知道那是什么,旧的情况会发生什么?我对框架知之甚少......)。真的,我只是发布这个,因为每个人都说这是不可能的,但实际上这只是一种荒谬的糟糕形式。 ;-)

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

你可以把不可变的对象一个可变的容器内;列表最容易。

此代码打印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类型列表,但像以前那样以其他方式使用相同的代码,就可以得到具有可变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`) 

实际上,您应该构造您的数据,以便上述“技巧”是多余的。这些例子不应该直接使用,但应该帮助你弄清楚该怎么做。

4

您可以使用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

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,像菜单= [A,F,G]此伪代码,我要插入位于索引1-4

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]