Question

Est-il possible en python pour incrémenter objet int en place, int ne semble pas mettre en œuvre __iadd__ donc + = 1 retourne en fait un nouvel objet

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

Ce que je veux est de rester n désignant un même objet.

Objectif: Je classe dérivée de int et je veux mettre en œuvre type C « ++ n » opérateur pour cette classe

Conclusion: ok comme int est immuable, il n'y a aucun moyen, on dirait que je vais devoir écrire mon propre quelque chose de classe comme ceci

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
Était-ce utile?

La solution

ints sont immuables, de sorte que vous devrez construire votre propre classe avec toutes les méthodes de l'int si vous voulez un « mutable int »

Autres conseils

Si vous devez absolument obtenir ce code de travail, voici une méthode sale, où une méthode d'instance se déplace un cadre et sa propre entrée écrase de la population locale. Je ne recommande pas. (Comme, vraiment pas. Je ne suis même pas sûr de ce qui le fait. Qu'est-ce qui se passe à l'ancienne instance? Je ne connais pas assez cadres ...). Vraiment, je signale que cela parce que tout le monde dit qu'il est impossible, alors qu'en réalité il est juste ridiculement mauvaise forme. ; -)

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,

sorties:

9 8 7 6 5 4 3 2 1

Vous pouvez utiliser ctypes comme des entiers mutables. Choisir le bon ctype sera important cependant, car elles limitent la taille entier qu'ils peuvent porter.

>>> 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
>>> 

Plus d'infos: https://docs.python.org /2/library/ctypes.html#fundamental-data-types

Il serait probablement plus facile de créer une classe qui implémente les méthodes int et encapsule un nombre entier interne.

Vous pouvez mettre un objet immuable dans un conteneur mutable; les listes sont plus faciles.

Ce code imprime 0, ce qui démontre le problème:

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`)

Si vous mettez l'int dans une liste, mais sinon utilisez le même code que précédemment, vous pouvez obtenir l'effet d'avoir un mutable int (si elle est la liste qui est vraiment subi une mutation):

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`)

Dans la pratique, vous devez structurer vos données afin que le « truc » ci-dessus est redondant. Les exemples ne doivent pas être utilisés directement, mais devraient vous aider à comprendre ce qu'il faut faire.

Oui, la réponse est que, ints sont immuables.

J'ai eu un problème similaire aujourd'hui et est venu avec une classe appelée IterInt qui vous permet d'incrémenter ou de décrémenter en place avec « + » et « - » décorateurs.

Utilisation:

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

Dans mon cas, j'avais une situation où je voulais modifier le menu existant d'une application en insérant plusieurs éléments de commande après un index spécifique. L'API fourni J'utilise a une fonction « addCommand » qui peut prendre un indice auquel insérer.

Considérons ce code pseudo où menu comporte des commandes a à g, quelque chose comme le menu = [a, f, g], et je veux insérer b-e à l'index 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]

Ce serait bien si je pouvais écrire si incréments IDX en place comme c où je pouvais faire IDX ++, mais les fonctions ne permettent pas de méthode dans les arguments de python IDX + = 1.

Solution:

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]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top