Подтвердить что ты не робот

Инкремент int object

Есть ли способ в python для инкремента int int на месте, int, похоже, не реализует __iadd__, поэтому + = 1 фактически возвращает новый объект

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

Я хочу, чтобы n оставалось указывать на один и тот же объект.

Назначение: у меня есть класс, полученный из int, и я хочу реализовать оператор типа С++ для этого класса

Вывод: ok, поскольку 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
4b9b3361

Ответ 1

ints неизменяемы, поэтому вам нужно будет создать собственный класс со всеми методами int, если вы хотите "mutable int"

Ответ 2

Вы можете использовать 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

Было бы легче создать класс, который реализует методы int и обертывает внутреннее целое число.

Ответ 4

Если вам абсолютно необходимо заставить этот код работать, вот грязный метод, когда метод экземпляра перемещается вверх по кадру и перезаписывает свою запись локальных локалей. Не рекомендовал бы. (например, действительно нет. Я даже не уверен, что это делает. Что происходит со старым экземпляром? Я недостаточно знаю о кадрах...). На самом деле, я только публикую это, потому что все говорили, что это невозможно, когда на самом деле это просто смехотворно плохая форма.; -)

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

Ответ 5

Вы можете поместить неизменяемый объект внутри изменяемого контейнера; списки проще всего.

Этот код печатает 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`)

На практике вы должны структурировать свои данные, чтобы вышеупомянутый "трюк" был избыточным. Примеры не должны использоваться напрямую, но должны помочь вам понять, что делать.

Ответ 6

Да, короткий ответ заключается в том, что ints неизменяемы.

Ответ 7

Сегодня у меня была аналогичная проблема и явился класс 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], и я хочу вставить b-e с индексом 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]