一个代码块可以工作,但另一个不能。这将是有意义的,除了第二个 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 += y
但 x
不提供 __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
。
奖金
关于python - i = i + n 真的和 i += n 一样吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52747784/