Вопрос по int, python – инкремент int объект

14

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

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

То, что я хочу, это чтобы n указывал на один и тот же объект.

Цель: у меня есть класс, производный от int, и я хочу реализовать тип C & amp; ++ n & apos; оператор для этого класса

Вывод: хорошо, так как 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
хм, я просто хочу показать моему другу, что питон может делать, пока --n: print n;) Anurag Uniyal
Посмотрите на это, если вы хотите сделать изящный, хотя и немного запутанный способ обернуть ваши int в анонимный класс (который может изменяться), который будет вести себя как «ссылка»:stackoverflow.com/a/1123054/409638 то есть ref = type ('', '((), {' 'n': 1}) robert
Почему вы хотите реализовать для него префиксный оператор? Собираетесь ли вы добавить собственный препроцессор для преобразования ++ n в вызов метода? Ryan

Ваш Ответ

7   ответов
0

Да, короткий ответ таков: целые числа неизменны.

3

Вероятно, было бы проще создать класс, реализующий методы int и обертывающий внутреннее целое число.

Не просто, но может быть единственным способом, поскольку целые числа не изменяемы
12

Интты являются неизменяемыми, поэтому вам нужно создать свой собственный класс со всеми методами int, если вы хотите & quot; изменяемый int & quot;

Не имеет значения, если целые числа класса являются неизменяемыми, значение атрибута является переменным, так что вы можете определить рабочийMutableInt класс, а не то, что вы когда-либо хотели.
Я сделал это:github.com/markrages/python_mutable_number
Целые числа в этом классе все еще будут неизменными.
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

Для записи, это медленнее, чем увеличение нормального целого числа.
Вероятно, это плохая идея по нескольким причинам, но в любом случае, спасибо, теперь я знаю стандартную вещь для импортаas mutable_int.
0

У меня была похожая проблема сегодня, и я предложил класс IterInt, который позволяет вам увеличивать или уменьшать на месте, используя & quot; + & quot; и & quot; - & quot; декораторы.

Использование:

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, который я использую, имеет & quot; addCommand & quot; функция, которая может взять индекс для вставки.

Рассмотрим этот псевдокод, в котором меню имеет команды от 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]
Это действительно плохая идея. Если вы начнете сx = IterInt(10), затем-x равняется9не-10, Перегрузка операторов должна использоваться для того, чтобы операторы работали с экземплярами пользовательских классов так же, как они работают со встроенными типами. Вы можете создавать новые операторы для новых типов, но это следует оставить опытным разработчикам API. Это слишком легко упустить из виду.
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
на несвязанной ноте кто-нибудь знает, возможно ли найти индекс элемента в кортеже без предварительного преобразования его в список? i = list (values) .index (self) кажется немного окольным.
+1 интересно, но да, я бы испугался, чтобы использовать это Anurag Uniyal
@Markus a = (1,2,3,4,5); a.index (3) приводит к 2. По крайней мере, это с Python 3
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       # t,he list that `a` and `b` point to is mutated
print(a[0])    # `a[0]` points to the same object as `b[0]` (the `1`)

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

Похожие вопросы