ここでの答えはどれも、Pythonの土地でこれがなぜ起こるのかを実際に説明するためのコードを提供しません。そして、これはより深いアプローチで見るのが楽しいので、ここに行きます。
これが期待どおりに機能しない主な理由は、Pythonで次のように書くときです。
i += 1
あなたが思っていることをやっていません。整数は不変です。これは、オブジェクトがPythonで実際に何であるかを調べると確認できます。
a = 0
print('ID of the first integer:', id(a))
a += 1
print('ID of the first integer +=1:', id(a))
id関数は、存続期間中のオブジェクトの一意で一定の値を表します。概念的には、C / C ++のメモリアドレスに大まかにマップします。上記のコードの実行:
ID of the first integer: 140444342529056
ID of the first integer +=1: 140444342529088
これは、IDが異なるためa
、1つ目は2つ目と同じではないことを意味しa
ます。事実上、それらはメモリ内の異なる場所にあります。
ただし、オブジェクトを使用する場合、動作は異なります。+=
ここで演算子を上書きしました:
class CustomInt:
def __iadd__(self, other):
# Override += 1 for this class
self.value = self.value + other.value
return self
def __init__(self, v):
self.value = v
ints = []
for i in range(5):
int = CustomInt(i)
print('ID={}, value={}'.format(id(int), i))
ints.append(int)
for i in ints:
i += CustomInt(i.value)
print("######")
for i in ints:
print('ID={}, value={}'.format(id(i), i.value))
これを実行すると、次の出力が得られます。
ID=140444284275400, value=0
ID=140444284275120, value=1
ID=140444284275064, value=2
ID=140444284310752, value=3
ID=140444284310864, value=4
######
ID=140444284275400, value=0
ID=140444284275120, value=2
ID=140444284275064, value=4
ID=140444284310752, value=6
ID=140444284310864, value=8
この場合のid属性は、オブジェクトの値が異なる場合でも、実際には両方の反復で同じであることに注意してください(id
オブジェクトが保持しているint値も見つけることができます。不変です)。
これを、不変オブジェクトで同じ演習を実行するときと比較してください。
ints_primitives = []
for i in range(5):
int = i
ints_primitives.append(int)
print('ID={}, value={}'.format(id(int), i))
print("######")
for i in ints_primitives:
i += 1
print('ID={}, value={}'.format(id(int), i))
print("######")
for i in ints_primitives:
print('ID={}, value={}'.format(id(i), i))
この出力:
ID=140023258889248, value=0
ID=140023258889280, value=1
ID=140023258889312, value=2
ID=140023258889344, value=3
ID=140023258889376, value=4
######
ID=140023258889280, value=1
ID=140023258889312, value=2
ID=140023258889344, value=3
ID=140023258889376, value=4
ID=140023258889408, value=5
######
ID=140023258889248, value=0
ID=140023258889280, value=1
ID=140023258889312, value=2
ID=140023258889344, value=3
ID=140023258889376, value=4
ここで注意すべき点がいくつかあります。まず、のループでは+=
、元のオブジェクトに追加しなくなりました。この場合、intはPythonの不変型の1つであるため、pythonは異なるIDを使用します。また、Pythonはid
、同じ不変の値を持つ複数の変数に対して同じ基礎を使用していることに注意してください。
a = 1999
b = 1999
c = 1999
print('id a:', id(a))
print('id b:', id(b))
print('id c:', id(c))
id a: 139846953372048
id b: 139846953372048
id c: 139846953372048
tl; dr -Pythonには少数の不変の型があり、これが表示される動作を引き起こします。すべての可変タイプについて、あなたの期待は正しいです。
i
は、不変であるか、非変更操作を実行している場合にのみ当てはまります。ネストされたリストを使用for i in a: a.append(1)
すると、動作が異なります。Python はネストされたリストをコピーしません。ただし、整数は不変であり、加算によって新しいオブジェクトが返されますが、古いオブジェクトは変更されません。