Python列表拼接疑问:为何append([]+a)有效而append(a)返回空列表?
问题描述
我尝试将两个列表names和ages按索引配对成嵌套列表(目标格式为[['John', '17'], ['Mike', '21']],练习用,知道可以用zip()但想手动实现),写出了如下代码:
names = ['Ana', 'John', 'Bob', 'Mike', 'July'] ages = ['17', '22', '33', '8', '76'] a = [] b = [] for i in range(len(names)): a.append(names[i]) a.append(ages[i]) b.append([] + a) # 这里用[] + a能得到预期结果 a.clear() print(b)
输出符合预期:[['Ana', '17'], ['John', '22'], ['Bob', '33'], ['Mike', '8'], ['July', '76']]。但我困惑的是:如果直接写b.append(a),最终会得到全空的列表b,而用b.append([] + a)却能成功,想请教这一现象的原因。
解答
这其实是Python中可变对象的引用特性在搞鬼,我来给你拆解清楚:
列表是可变对象,存储的是引用
Python里的列表属于可变容器,变量a存储的并不是列表里的元素本身,而是指向这个列表在内存中位置的一个“引用”(类似内存地址)。直接append(a)的问题
当你执行b.append(a)时,你并没有把a里的元素复制一份放进b,而是把a的引用直接加到了b里。这时候b里的所有元素,其实都指向同一个内存地址里的列表(也就是a对应的那个列表)。
之后你调用a.clear(),这个操作会直接清空a指向的内存中的列表内容——因为b里的所有元素都和a指向同一个列表,所以最后打印b时,看到的就是一堆空列表。[] + a为什么能成功
[]是一个全新的空列表,+运算符会把a里的元素逐个复制到这个新列表中,生成一个独立的新列表对象。这时候你把这个新列表的引用加到b里,它和原来的a没有任何关联——哪怕之后清空a,b里的新列表也不会受到影响,所以能得到你想要的嵌套列表结果。更规范的替代写法
其实还有更直观、可读性更强的写法可以生成列表副本,比如:b.append(a.copy()):调用列表的copy()方法直接生成副本b.append(list(a)):通过list()构造器创建新列表
这些写法在日常开发中比[] + a更常用。
内容的提问来源于stack exchange,提问作者Burak Baris

