i = i + n是否真的与i + = n相同? [英] Is i = i + n truly the same as i += n?

查看:96
本文介绍了i = i + n是否真的与i + = n相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个代码块有效,而另一块无效.这是有意义的,除了第二个块与第一个块相同之外,只有使用简写形式的操作.它们实际上是相同的操作.

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")串联到列表


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

解决方案

它们不必相同.

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

如果您使用x += y,但是x不提供__iadd__方法(或者该方法返回NotImplemented),则将__add__用作后备广告,这意味着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__实现了扩展行为.

演示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)的挑战,以便在文档中找到它

One block of code works but the other does not. Which would make sense except the second block is the same as the first only with an operation written in shorthand. They are practically the same operation.

l = ['table']
i = []

Version 1

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

Output: ['t', 'a', 'b', 'l', 'e']

Version 2

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

Output:

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


What is causing this strange error?

解决方案

They don't have to be the same.

Using the + operator calls the method __add__ while using the += operator calls __iadd__. It is completely up to the object in question what happens when one of these methods is called.

If you use x += y but x does not provide an __iadd__ method (or the method returns NotImplemented), __add__ is used as a fallback, meaning that x = x + y happens.

In the case of lists, using l += iterable actually extends the list l with the elements of iterable. In your case, every character from the string (which is an iterable) is appended during the extend operation.

Demo 1: using __iadd__

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

Demo 2: using extend does the same

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

Demo 3: adding a list and a string raises a TypeError.

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

Not using += gives you the TypeError here because only __iadd__ implements the extending behavior.

Demo 4: common pitfall: += does not build a new list. We can confirm this by checking for equal object identities with the is operator.

>>> 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]

However, the l = l + iterable syntax does build a new list.

>>> 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
[]

In some cases, this can produce subtle bugs, because += mutates the original list, while
l = l + iterable builds a new list and reassigns the name l.

BONUS

Ned Batchelder's challenge to find this in the docs

这篇关于i = i + n是否真的与i + = n相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆