Python中列表+=、append操作差异及末尾逗号的作用解析
Python列表操作中末尾逗号的运行逻辑说明
首先要明确两个容易被忽略的Python基础规则,所有观察到的现象都是这两个规则共同作用的结果:
- 元组的核心标识是逗号,不是括号。除了空元组必须写
()之外,单元素元组的写法就是值后面直接加逗号,比如1,、[1],实际都是单元素元组,括号在绝大多数场景只是用来做语法分隔、调整优先级,不是生成元组的必要条件。 x += y和x = x + y并不等价。前者是调用变量指向对象的__iadd__(就地加)方法,直接修改原对象(如果对象支持就地修改的话);后者是先计算等号右侧的完整表达式,生成新对象后再把变量名绑定到新对象上。另外所有赋值类运算符(=、+=、-=等)的优先级是Python所有运算符里最低的,比逗号运算符的优先级还要低。
循环场景下4种写法的逻辑拆解
基础测试代码如下:
re = [] for i in range(5): # 填充不同逻辑
不同写法的执行逻辑:
- 执行
re.append(i):append方法会把传入的参数直接作为单个元素追加到列表末尾,传入的是整数i,所以最终结果为[0,1,2,3,4]。 - 执行
re.append([i]):传入的参数是[i]这个单元素列表,所以每次追加的元素是列表类型,最终结果为[[0],[1],[2],[3],[4]]。 - 执行
re += [i]:列表的__iadd__方法要求传入可迭代对象,会遍历可迭代对象把内部元素逐个追加到原列表。这里传入的是列表[i],遍历后拿到的元素是整数i,所以最终结果和append(i)一致,为[0,1,2,3,4]。 - 执行
re += [i],:因为+=优先级比逗号低,等号右侧的实际运算结果是单元素元组([i],)——元组里唯一的元素是[i]列表。列表的__iadd__遍历这个元组时,拿到的元素就是[i]列表本身,所以每次追加一个列表元素,最终结果为[[0],[1],[2],[3],[4]]。“末尾逗号会生成元组”的判断是完全正确的,这里生成的元组是包裹了[i]的外层容器,被+=遍历展开后,内部的[i]会作为整体被追加,所以元素类型是列表完全符合逻辑。
额外测试的re += i,写法逻辑完全一致:右侧的i,是单元素元组(i,),遍历后拿到的元素是整数i,所以追加后结果还是[0,1,2,3,4],和re += [i]效果一致,只是承载i的可迭代容器从列表换成了元组而已。
对照测试的逻辑拆解
第一组对照:
re = [] re = re + [1]
等号右侧是两个列表做拼接,生成新列表[1]后绑定给变量re,所以最终re的值是列表[1]。
如果给行尾加逗号:
re = [] re = re + [1],
因为=优先级低于逗号,等号右侧会先计算re + [1]得到列表[1],再通过末尾逗号生成单元素元组([1],),最后把这个元组绑定给re,所以此时re的类型变成元组,值为([1],)。
循环报错场景的逻辑拆解
正常写法:
re = [] for i in range(5): re = re + [i]
每次循环时re都是列表,和[i]拼接后生成新列表再绑定给re,所以最终结果为[0,1,2,3,4]。
加逗号后的写法:
re = [] for i in range(5): re = re + [i],
第一次循环时,初始re是空列表,计算re + [0]得到列表[0],加逗号生成元组([0],)绑定给re——这一步结束后re已经从列表变成了元组。第二次循环计算re + [i]时,re是元组类型,Python中元组只支持和元组类型拼接,不支持和列表拼接,所以会直接抛出TypeError: can only concatenante tuple (not "list") to tuple错误。
内容的提问来源于stack exchange,提问作者Mr.Bagel
相关产品推荐
相关产品推荐

