当b是列表时,为什么b + =(4,)有效而b = b +(4,)不起作用?

Sup*_*ppu 75 python tuples list python-3.x

如果我们采取b = [1,2,3]并尝试这样做:b+=(4,)

它返回b = [1,2,3,4],但是如果我们尝试这样做b = b + (4,)是行不通的。

b = [1,2,3]
b+=(4,) # Prints out b = [1,2,3,4]
b = b + (4,) # Gives an error saying you can't add tuples and lists
Run Code Online (Sandbox Code Playgroud)

我预计b+=(4,)会失败,因为您无法添加列表和元组,但它确实有效。因此,我尝试b = b + (4,)期望得到相同的结果,但是没有用。

Kar*_*tel 70

“为什么”问题的问题在于它们通常可能意味着多种不同的事物。我会尝试回答我认为您可能会想到的每个问题。

“为什么它可能有不同的工作方式?” 这可以通过例如this来回答。基本上,+=尝试使用不同的对象方法:(__iadd__仅在左侧检查),vs __add____radd__(“反向添加”,在左侧没有检查的情况下在右侧检查__add__)为+

“每个版本到底做什么?” 简而言之,该list.__iadd__方法的功能与之相同list.extend(但由于语言设计的原因,仍然存在分配问题)。

例如,这也意味着

>>> a = [1,2,3]
>>> b = a
>>> a += [4] # uses the .extend logic, so it is still the same object
>>> b # therefore a and b are still the same list, and b has the `4` added
[1, 2, 3, 4]
>>> b = b + [5] # makes a new list and assigns back to b
>>> a # so now a is a separate list and does not have the `5`
[1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

+,当然会创建一个新对象,但是显式地需要另一个列表,而不是尝试将元素拉出不同的顺序。

“为什么这样做对+ =有用?它效率更高;该extend方法不必创建新对象。当然,有时这会产生一些令人惊讶的效果(如上所示),通常Python并不是真正意义上的效率,但这些决定是很久以前做出的。

“为什么不允许使用+添加列表和元组的原因是什么?” 这里(谢谢@ splash58); 一种想法是(tuple + list)应该产生与(list + tuple)相同的类型,并且不清楚结果应该是哪种类型。+=没有这个问题,因为a += b显然不应该更改的类型a

  • 集的并集运算符是`|`而非`+`。 (7认同)
  • 哦,非常正确。并且列表不使用`|`,因此有点毁了我的示例。如果以后再想一个更清晰的示例,我将其替换。 (2认同)

alf*_*sin 21

它们不等效:

b += (4,)
Run Code Online (Sandbox Code Playgroud)

是以下内容的简写:

b.extend((4,))
Run Code Online (Sandbox Code Playgroud)

同时+连接列表,因此:

b = b + (4,)
Run Code Online (Sandbox Code Playgroud)

您正在尝试将元组连接到列表


Cha*_* DZ 14

执行此操作时:

b += (4,)
Run Code Online (Sandbox Code Playgroud)

转换为此:

b.__iadd__((4,)) 
Run Code Online (Sandbox Code Playgroud)

它在后台调用b.extend((4,))extend接受一个迭代器,这也为什么起作用:

b = [1,2,3]
b += range(2)  # prints [1, 2, 3, 0, 1]
Run Code Online (Sandbox Code Playgroud)

但是当您这样做时:

b = b + (4,)
Run Code Online (Sandbox Code Playgroud)

转换为此:

b = b.__add__((4,)) 
Run Code Online (Sandbox Code Playgroud)

仅接受列表对象。