为什么在Python中列表和字符串不能使用“+”运算符进行连接?

4

我想解释一下list +='a'list=list+'a'之间的区别。比如说,如果我执行以下操作:

li=[]
for i in 'string':
    li+=i

我没有收到错误信息,但是如果使用第二个选项,按照惯例应该是相同的,但会出现错误。

li=[]
for i in 'string':
    li=li+i

TypeError: 只能将列表 (list) 与列表相加,不能将字符串 (str) 与列表相加。 正确的做法是像下面这样:
li=[]
for i in 'string':
    li=li+[i]

我想知道+= 运算符是如何工作的?它是如何获取列表中的字符串,它会将字符串转换为列表吗?


2
+= 的返回类型是明确的:它是左操作数的类型。+ 的返回类型不清楚。程序员期望 list + str 返回一个列表还是字符串? - khelwood
2
为什么在列表上使用+=会出现意外行为? - Sayse
@khelwood 应该返回 list - M_S_N
1
这个回答解决了你的问题吗?为什么在列表上使用+=会出现意外行为? - Meha Parekh
@M_S_N 是的,我明白这是在这种用例中想要的。但并不适用于每个开发者在每种可能的用例中。 - khelwood
显示剩余2条评论
2个回答

2
我想知道 += 操作符是如何工作的?
就地赋值操作符 += 有两种方式(来自文档):
1. 对于不可变对象
对于不可变目标,如字符串、数字和元组,会计算更新后的值,但不会将其分配回输入变量。
这意味着每次使用 += 时(如果您的对象是不可变的),都会创建一个新的对象。
2. 对于可变对象
对于可变目标,如列表和字典,就地方法将执行更新,因此不需要后续赋值。
这意味着每次使用 += 时(如果您的对象是可变的),都不会创建一个新的对象。
在你的例子中,如果要使用 li+=i,你必须确保 i 是一个列表,否则将无法工作。
li = []
for i in 'string':
    li = li + [i]

你正在连接两个列表,但每次都创建一个新的列表li,你可以使用内置函数id来检查:
li=[]
for i in '1':
    print(id(li))
    li=li+[i]
    print(id(li))

输出:

140661631713104
140661644452240

您可以像这样使用就地赋值操作符+=
li=[]
for i in '1':
    print(id(li))
    li += [i]
    print(id(li))

输出:

140661641698592
140661641698592

如您所见,元素被添加到li列表中而不创建新的li列表,这更有效率,这与list.extend完全相同。
要添加另一个元素到您的列表中,而不使用列表,您可以使用list.append

你的回答很有道理,但这仍然是一个非常奇怪的设计选择,特别是来自另一种语言,其中类似 a+=a 的东西等同于 a= a+a - M_S_N

1
Python文档表示:
要了解这种情况发生的原因,您需要知道:(a)如果一个对象实现了__iadd__魔术方法,则在执行+=增强赋值时会调用它,并且它的返回值是在赋值语句中使用的;而(b)对于列表,__iadd__等效于在列表上调用extend并返回列表。这就是为什么我们说对于列表,+=是list.extend的“简写”的原因。
由于list.extend期望一个迭代器,而字符串是可迭代的,所以在您给出的示例中,+=有效。这意味着,您甚至不需要for循环,因为list.extend将遍历字符串并将元素添加到列表中。 li=[] li += "string" 输出: ['s', 't', 'r', 'i', 'n', 'g']
列表只能连接(+)列表。

Source:
https://docs.python.org/3/tutorial/datastructures.html https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types https://docs.python.org/3/faq/programming.html#faq-augmented-assignment-tuple-error


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接