16

Pythonにintオブジェクトを適切にインクリメントする方法はありますか?intは実装されていないようです__iadd__ので、+=1は実際に新しいオブジェクトを返します

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

7 に答える 7

13

intは不変であるため、「可変int」が必要な場合は、すべてのintのメソッドを使用して独自のクラスを作成する必要があります。

于 2009-07-16T04:10:55.603 に答える
8

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

于 2015-02-27T05:09:32.073 に答える
6

そのコードをどうしても機能させる必要がある場合は、ここにダーティメソッドがあります。このメソッドでは、インスタンスメソッドがフレームを上に移動し、独自のローカルエントリを上書きします。お勧めしません。(たとえば、実際にはそうではありません。それが何をするのかさえわかりません。古いインスタンスはどうなりますか?フレームについて十分に知りません...)。本当に、私はこれを投稿しているのは、誰もがそれは不可能だと言ったからですが、実際にはそれはばかばかしいほど悪い形です。;-)

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
于 2009-07-16T23:44:29.413 に答える
4

intメソッドを実装し、内部整数をラップするクラスを作成する方がおそらく簡単でしょう。

于 2009-07-16T04:10:36.447 に答える
4

不変オブジェクトを可変コンテナ内に置くことができます。リストが最も簡単です。

このコードは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`)

実際には、上記の「トリック」が冗長になるようにデータを構造化する必要があります。例を直接使用するべきではありませんが、何をすべきかを理解するのに役立つはずです。

于 2013-09-09T14:24:02.957 に答える
0

はい、簡単に言えば、intは不変です。

于 2009-07-16T04:11:45.523 に答える
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」関数があります。

menuにコマンドaからgがあり、menu = [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]
于 2017-07-14T23:05:09.590 に答える