Python 使用增广赋值向列表中添加字符串
这里发生了什么?这不应该起作用,对吗?还是我遗漏了一些明显的东西Python 使用增广赋值向列表中添加字符串,python,string,list,augmented-assignment,Python,String,List,Augmented Assignment,这里发生了什么?这不应该起作用,对吗?还是我遗漏了一些明显的东西 >>> b = [] >>> c = '1234' >>> b += c >>> b ['1', '2', '3', '4'] >>> >b=[] >>>c='1234' >>>b+c 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 b+c TypeError:只能将列表(而不是“str”)连接到列表 >>> 那么a+=b并不总
>>> b = []
>>> c = '1234'
>>> b += c
>>> b
['1', '2', '3', '4']
>>>
>b=[]
>>>c='1234'
>>>b+c
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
b+c
TypeError:只能将列表(而不是“str”)连接到列表
>>>
那么
a+=b
并不总是等同于a=a+b
?字符串是一个字符序列。列表操作+=
获取任何序列,并将序列的每个元素追加到列表中
(实际上,
+=
接受任何iterable。)字符串是iterable:元素是字符串的字符。将iterable添加到列表时,iterable的元素将附加到列表中
以下任一项都将执行您期望的操作(即追加字符串,而不是使用字符串的字符扩展列表):
或
+=
运算符扩展列表而不是附加到列表:
b.append(c)
你期待什么?如果要将c添加为字符串,则必须执行以下操作:
>>> b = []
>>> c = "1234"
>>> b.append(c)
>>> b
['1234']
>>> b.extend(c)
>>> b
['1234', '1', '2', '3', '4']
>>> b += c
>>> b
['1234', '1', '2', '3', '4', '1', '2', '3', '4']
>>> b += [c]
>>> b
['1234', '1', '2', '3', '4', '1', '2', '3', '4', '1234']
干杯 本质上,列表上的+=运算符将检索c的迭代器,它将按顺序生成各个字符。如果您打算将实际字符串添加到列表中,从而产生结果['1234',],则可以使用b.append('1234')。+=是扩展的语法糖,但+只是列表连接。如果扩展,将迭代参数,在本例中,参数是字符串。但是您不能将字符串连接到列表,因此+失败。这不是对原始问题的回答(我认为已经得到了充分的回答),而是对注释中关于增广赋值语义的众多问题的回答(
+=
和类似操作)
简言之:扩充赋值对可变类型的作用不同于对不可变类型的作用
str
,tuple
,以及数字类型等都是不可变的。元组的内容在创建后无法更改,因此会出现以下行为:
b.append(c)
str
具有相同的语义。基本上,a+=b
等于a=a+b
,如果a
是不可变的
大多数其他类型,包括列表
,都是可变的。列表的内容可以就地更改,而增广赋值正是这样做的。因此:
>>> a = (1, 2)
>>> b = a
>>> a += (3, 4)
>>> a
(1, 2, 3, 4)
>>> b
(1, 2)
而如果第三行被替换为a=a+[3,4]
,则将创建一个新列表,而b
将是[1,2]
对于用户定义的类,语义取决于它是如何实现的,但这是按照PEP203应该如何实现的。
+
是一个不同于+=
的运算符。我知道,它被称为增广分配,它被定义为等同于a=a+b(参见PEP203)。严格地接受这个定义会让我产生错误的期望。这让我感到惊讶(可能我从来不敢在python代码中向字符串添加列表,所以我以前从未与此冲突)。在面临歧义时,不应,拒绝猜测的诱惑。
?。但正如蒂姆在上文中解释的那样,+=的行为与+,请参阅蒂姆帖子上的评论。你知道这些操作符(+
,+=
)对iterables/序列的影响的文档来源吗@moooeeep-in-您还可以看到它在实际源代码中是如何发生的。这种行为在Python3.x中仍然存在吗?我总是觉得标准库类型破坏了a+=b
a=a+b
(不影响对原始a
值的任何其他引用)的一般约定,这让我很恼火。@Karl Knechtel:不幸的是,它仍然存在于Python 3.2.1中。我在Python 3.2中检查过它,是的。我发现问题在于初学者的代码产生了错误的结果。在学习Python
中,我找不到任何关于这种特定行为的参考。我检查了PEP203,它说使用了\uuuuuidd\uuuu
,但他们也说\uuuuidd\uuuuu
是就地\uuuuuuu添加
,在本例中并非如此。。。也许有人可以解释这种行为背后的理性,或者指出/链接到一些关于它的讨论?我从卡尔的评论中了解到,有人对此表示担忧。这是一个非常好的观察结果a
和b
共享相同的内存地址,直到在赋值运算符的左侧计算a
?你能把它包括在内吗?
b.append(c)
>>> a = (1, 2)
>>> b = a
>>> a += (3, 4)
>>> a
(1, 2, 3, 4)
>>> b
(1, 2)
>>> a = [1, 2]
>>> b = a
>>> a += [3, 4]
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3, 4]