python - 什么时候 "i += x"与 Python 中的 "i = i + x"不同?

有人告诉我,+= 的效果与标准的 i = i + 表示法不同。是否存在 i += 1i = i + 1 不同的情况?

最佳答案

这完全取决于对象i

+= 调用 __iadd__ method (如果存在——如果不存在则返回 __add__)而 + 调用 __add__ method 1__radd__ method in a few cases 2.

从 API 的角度来看,__iadd__ 应该用于修改可变对象就地(返回被变异的对象),而 __add__ 应该返回一个新实例的东西。对于 immutable 对象,这两个方法都返回一个新实例,但 __iadd__ 会将新实例放在当前命名空间中,并与旧实例具有相同的名称。这就是为什么

i = 1
i += 1

似乎增加了i。实际上,您得到一个新整数并将其分配在“i 之上——失去对旧整数的一个引用。在这种情况下,i += 1i = i + 1 完全相同。但是,对于大多数可变对象,情况就不同了:

作为一个具体的例子:

a = [1, 2, 3]
b = a
b += [1, 2, 3]
print(a)  # [1, 2, 3, 1, 2, 3]
print(b)  # [1, 2, 3, 1, 2, 3]

相比:

a = [1, 2, 3]
b = a
b = b + [1, 2, 3]
print(a)  # [1, 2, 3]
print(b)  # [1, 2, 3, 1, 2, 3]

注意在第一个示例中,由于 ba 引用相同的对象,当我在 b 上使用 +=,它实际上改变了 b(并且 a 也看到了这种变化——毕竟,它引用的是同一个列表)。然而,在第二种情况下,当我执行 b = b + [1, 2, 3] 时,这会获取 b 正在引用的列表并将其与新列表连接起来[1、2、3]。然后它将连接的列表存储为当前命名空间中的 b -- 不考虑之前的行是什么 b


1在表达式 x + y 中,如果 x.__add__ 没有实现或者如果 x. __add__(y) 返回 NotImplemented and xy 有不同的类型,然后 x + y 尝试调用 y.__radd__(x) .所以,如果你有

foo_instance += bar_instance

如果 Foo 没有实现 __add____iadd__ 那么这里的结果和

foo_instance = bar_instance.__radd__(bar_instance, foo_instance)

2在表达式foo_instance + bar_instance中,bar_instance.__radd__会在foo_instance.__add__之前尝试code> if bar_instance 的类型是 foo_instance 类型的子类(例如 issubclass(Bar, Foo))。这样做的理由是 Bar 在某种意义上比 Foo 是一个“更高级别”的对象,因此 Bar 应该获得覆盖 Foo 的行为。

关于python - 什么时候 "i += x"与 Python 中的 "i = i + x"不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15376509/

相关文章:

linux - 在 Linux 中更改默认 shell

python - cron 和 virtualenv

python - 有没有办法在 Python 中使用 PhantomJS?

windows - Windows 和 Linux 目录名称中禁止使用哪些字符?

linux - Linux 中是否有任何标准的退出状态代码?

python - 如何格式化小数以始终显示 2 个小数位?

linux - 在每行的开头添加前缀字符串

python - 转义正则表达式字符串

linux - 如何在 Vimdiff 中展开/折叠差异部分?

linux - 在 Linux 中自动重复命令