python - i = i + n 真的和 i += n 一样吗?

标签 python python-3.x operator-overloading

一个代码块可以工作,但另一个不能。这将是有意义的,除了第二个 block 与第一个 block 相同,只是用速记编写的操作。它们实际上是相同的操作。

l = ['table']
i = []

版本 1

for n in l:
    i += n
print(i)

输出:['t', 'a', 'b', 'l', 'e']

版本 2

for n in l:
    i = i + n
print(i)

输出:

TypeError: can only concatenate list (not "str") to list


是什么导致了这个奇怪的错误?

最佳答案

它们不必相同。

使用 + 运算符调用方法 __add__,而使用 += 运算符调用 __iadd__。调用这些方法之一时会发生什么完全取决于相关对象。

如果您使用 x += yx 不提供 __iadd__ 方法(或该方法返回 NotImplemented),__add__ 被用作 fallback,这意味着 x = x + y 发生。

在列表的情况下,使用 l += iterable 实际上使用 iterable 的元素扩展列表 l。在您的情况下,字符串中的每个字符(它是一个可迭代的)都在 extend 操作期间附加。

演示1:使用__iadd__

>>> l = []
>>> l += 'table'
>>> l
['t', 'a', 'b', 'l', 'e']

演示 2:使用 extend 也是如此

>>> l = []
>>> l.extend('table')
>>> l
['t', 'a', 'b', 'l', 'e']

演示 3:添加列表和字符串会引发 TypeError

>>> l = []
>>> l = l + 'table'
[...]
TypeError: can only concatenate list (not "str") to list

不使用 += 会在此处为您提供 TypeError,因为只有 __iadd__ 实现了扩展行为。

Demo 4:常见陷阱:+= 不会建立新列表。我们可以通过使用 is 运算符检查相等的对象身份来确认这一点。

>>> l = []
>>> l_ref = l # another name for l, no data is copied here
>>> l += [1, 2, 3] # uses __iadd__, mutates l in-place
>>> l is l_ref # confirm that l and l_ref are names for the same object
True
>>> l
[1, 2, 3]
>>> l_ref # mutations are seen across all names
[1, 2, 3]

但是,l = l + iterable 语法确实构建了一个新列表。

>>> l = []
>>> l_ref = l # another name for l, no data is copied here
>>> l = l + [1, 2, 3] # uses __add__, builds new list and reassigns name l
>>> l is l_ref # confirm that l and l_ref are names for different objects
False
>>> l
[1, 2, 3]
>>> l_ref
[]

在某些情况下,这可能会产生细微的错误,因为 += 变异 原始列表,而
l = l + iterable 构建一个 new 列表并重新分配名称 l

奖金

Ned Batchelder's challenge to find this in the docs

关于python - i = i + n 真的和 i += n 一样吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52747784/

相关文章:

python - 如何使用 python 脚本从一台远程服务器连接到另一台远程服务器?

python - 在 MAC OS X 10.9 上安装 NLTK 真的很困难

Python:从 Web 界面运行时导入其他 python 文件

python - 用 c 扩展 python 时,如何处理任意大小的整数?

c++ - 重载 + 运算符必须采用无参数或单参数链表

python - df.plot 添加到自身而不是单独的图中

python-3.x - python 函数文档中的 [x]* 是什么意思?

python - 使用 BeautifulSoup 提取跨度类文本时没有返回

C# 中的运算符重载

c++ - 小于运算符不能作为成员函数重载