i = i + n 真的和 i += n 一样吗? [复制]
Posted
技术标签:
【中文标题】i = i + n 真的和 i += n 一样吗? [复制]【英文标题】:Is i = i + n truly the same as i += n? [duplicate] 【发布时间】:2019-03-15 19:28:26 【问题描述】:一个代码块可以工作,但另一个不能。这将是有意义的,除了第二个块与第一个块相同,只是用速记编写的操作。它们实际上是相同的操作。
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:只能将列表(不是“str”)连接到列表
是什么导致了这个奇怪的错误?
【问题讨论】:
不,列表不一样。+=
扩展了一个列表。 +
将两个列表连接成一个新列表。
理想情况下,如果您在代码中使用此想法,则分别使用append()
和extend()
方法添加元素和连接列表可能更安全,以避免这样的歧义。
【参考方案1】:
它们不必相同。
使用+
运算符调用__add__
方法,而使用+=
运算符调用__iadd__
。调用这些方法之一时会发生什么完全取决于相关对象。
如果您使用x += y
,但x
没有提供__iadd__
方法(或该方法返回NotImplemented
),则__add__
用作fallback,这意味着@ 987654331@ 发生。
在列表的情况下,使用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__
实现了扩展行为。
演示 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
构建一个新列表和重新分配名称l
。
奖金
Ned Batchelder's challenge to find this in the docs
【讨论】:
【参考方案2】:没有。
7.2.1. Augmented assignment statements:
像
x += 1
这样的增强赋值表达式可以重写为x = x + 1
以实现类似但不完全相等的效果。 在增强版本中,x 只计算一次。此外,在可能的情况下, 实际操作是就地执行的,这意味着而不是 创建一个新对象并将其分配给目标,旧对象 改为修改。
【讨论】:
【参考方案3】:如果在第二种情况下,您在n
周围加上一个列表以避免错误:
for n in l:
i = i + [n]
print(i)
你得到
['table']
所以它们是不同的操作。
【讨论】:
以上是关于i = i + n 真的和 i += n 一样吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章