Python创建列表的正确姿势

本文探讨了Python中列表的浅拷贝与深拷贝的区别,通过实例说明了`[[]]*10`与`[[] for _ in range(10)]`创建方式的内存影响。理解如何避免子列表共享内存并创建独立副本至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果按照下面的方式创建了一个表中表:

a = [[]] * 10

这事用来存放对应位数上的元素的。在append元素的时候发现所有子列表是一起变化的。很自然的想到子列表是共用同一个地址的。查看一下内存地址果然如此。

a = [[]] * 10
for i in a:
    print(id(i))

[out]:
2502709438920
2502709438920
2502709438920
2502709438920
2502709438920
2502709438920
2502709438920
2502709438920
2502709438920
2502709438920

不用理会在内存中的具体地址是多少,只需要知道每一个列表的地址是一样的就可以了。列表的对应关系如下图所示。

image-20210422145549029


我们知道,在python中给列表赋值有直接赋值(添加一个地址指针)和拷贝赋值(copy)等方式。

a = [1,2,3]
b = a
c = a.copy()

在上面的例子中,b和a变量指向的内存地址是一样的,改变a或b的值另外一个也会相应的变化,而c则是独立出来的新变量,c的值与ab的值之间不会相互影响,他们的关系如下:

image-20210422150330792

采用a = [[]] * 10这种方式创建10个子空列表相当于将一个空列表复制十遍但是指向地址还是同一个,所以改变其中一个子列表的值其他子列表的值相应的发生改变。


那么正确的创建方式是什么呢。亲测使用[[] for _ in range(10)]可以创建相互独立的子列表。此方式在创建的时候每一次循环都单独生成一个新的地址空间上的列表来添加进原来的列表中。可以查看他们的内存地址:

a = [[] for _ in range(10)]
for i in a:
    print(id(i))
    
[out]:
    1999785117192
    1999785222472
    1999785222344
    1999785102344
    1999784963272
    1999785222536
    1999785222600
    1999785222792
    1999785222856
    1999785222728

可以看到,这种方式创建出来的列表的地址空间是完全不一样的,结构如下:

image-20210422151109215


当然,如果采用循环对同一个变量进行创建,那么它的地址任然是一样的:

x = []
a = [x for _ in range(10)]
for i in a:
    print(id(i))
    
[out]:
    3005231884744
    3005231884744
    3005231884744
    3005231884744
    3005231884744
    3005231884744
    3005231884744
    3005231884744
    3005231884744
    3005231884744

image-20210422151416752

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值