这里的答案都没有给您提供任何可用来真正说明为什么在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
这意味着第一个a
不再与第二个相同a
,因为它们的ID不同。实际上,它们位于内存中的不同位置。
但是,对于一个对象,事物的工作方式有所不同。我在+=
这里覆盖了运算符:
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值的in ,该值随着变量的变化而变化-因为整数是不可变的)。
与使用不可变对象进行相同练习时进行比较:
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
这里有几件事要注意。首先,在带有的循环中+=
,您不再添加到原始对象。在这种情况下,因为ints是Python中不可变的类型之一,所以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 不会复制嵌套列表。但是,整数是不可变的,加法会返回一个新对象,它不会更改旧对象。