为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

尚方宝剑之说 2021-07-03 10:00:07
一个代码块有效,但另一个无效。这是有意义的,除了第二个块与第一个块相同,只有一个用速记写的操作。它们实际上是相同的操作。l = ['table']i = []版本 1for n in l:    i += nprint(i)输出: ['t', 'a', 'b', 'l', 'e']版本 2for n in l:    i = i + nprint(i)输出:类型错误:只能将列表(不是“str”)连接到列表是什么导致了这个奇怪的错误?
查看完整描述

2 回答

?
波斯汪

TA贡献1811条经验 获得超4个赞

它们不必相同。


使用+运算符调用方法的__add__同时使用+=运算符调用__iadd__。调用这些方法之一时会发生什么完全取决于所讨论的对象。


如果您使用x += y但x不提供__iadd__方法(或方法返回NotImplemented),__add__则用作回退,这意味着x = x + y会发生。


在列表的情况下, usingl += iterable实际上l使用 的元素扩展列表iterable。在您的情况下,字符串中的每个字符(它是可迭代的)都在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构建新列表并重新分配name l。


查看完整回答
反对 回复 2021-07-13
?
千巷猫影

TA贡献1829条经验 获得超7个赞

如果在第二种情况下,您环绕一个列表n以避免错误:


for n in l:

    i = i + [n]

print(i)

你得到


['table']

所以它们是不同的操作。


查看完整回答
反对 回复 2021-07-13
  • 2 回答
  • 0 关注
  • 268 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信