Python中列表乘法和列表推导式的区别举例详解

 更新时间:2025年04月07日 11:01:53   作者:程序员阿甘  
在Python中列表是一种非常灵活和强大的数据结构,支持多种运算和操作,这篇文章主要介绍了Python中列表乘法和列表推导式区别的相关资料,文中通过代码就介绍的非常详细,需要的朋友可以参考下

可变对象与不可变对象

python中对象有两种类型:

  • 可变对象类型:list、dict、set
  • 不可变对象类型:tuple、string、int、float、bool

我们可以简单理解为:

  • 可变对象类型的变量中记录是:对象的地址值
  • 不可变对象类型的变量中记录时:对象的值

可变对象类型变量 list1 和 list2 可以通过相同地址值,指向同一个对象

list1 = [1, 2, 3, 4, 5]
list2 = list1  # 将list1的地址值赋给list2,使得list1,list2指向同一个对象

list1[0] = 2  # list1 修改对象内容

print(list1)
print(list2)  # list2 和 list1 指向的是同一个对象,因此list2打印结果和list1相同

但是不可变对象类型的变量,不具备上面特点

num1 = 10
num2 = num1

num1 -= 1

print(num1)  # 9
print(num2)  # 10

生成含 x 个 不可变对象 的列表

列表乘法

list1 = [0] * 2

列表推导式

list2 = [0 for _ in range(2)]

 由于 0 是不可变对象,因此这两种方式生成的列表没有区别。

生成含 x 个 可变对象 的列表

 列表乘法

list1 = [[]] * 2

列表推导式

list2 = [[] for _ in range(2)]

[]列表,属于可变对象,此时上面两种方式生成的列表是有区别的

list1 = [[]] * 2
list2 = [[] for _ in range(2)]

print(list1)  # [[], []]
print(list2)  # [[], []]

list1[0].append(0)
list2[0].append(0)

print(list1)  # [[0], [0]]
print(list2)  # [[0], []]

通过运行上面代码,我们可以发现,list1的打印结果似乎不太对劲。我们只是向 list1[0] 中追加了一个数值0,但是list1[1] 也被追加了一个数值0。

而 list2 没有发生这样的问题。

列表类型属于可变对象类型,列表类型的变量本质记录的是对象的地址值,我们可以使用id函数来获取对象的地址值,因此我们可以将 list1 和 list2 内部元素的地址值打印出来看看

list1 = [[]] * 2
list2 = [[] for _ in range(2)]

print(list(map(id, list1)))  # [2779372310784, 2779372310784]
print(list(map(id, list2)))  # [2779372317376, 2779372633152]

可以发现,list1 中两个元素的对象地址值是相同的,而 list2 中两个元素的对象地址值是不相同的。

也就是说,list1中虽然有两个元素,但是这两个元素的对象地址值相同,即指向同一个对象,就好比两条绳子(变量)A,B牵着一头牛(对象),你通过绳子 A 把牛拽过来给它挂了个铃铛后,你再通过绳子 B 再把牛拽过来,发现它就是刚刚被挂铃铛的牛。

牛是同一头牛,但是有两条绳子牵着它。你无论通过哪个绳子拽牛,拽来的都是同一头牛。

也就说,列表乘法不会生成新的牛,只是生成了牵着同一头牛的多条绳子。

那么列表推导式,是会生成新的牛吗?我们不妨再看下面代码:

ele = []
list2 = [ele for _ in range(2)]

print(list2)  # [[], []]

list2[0].append(0)

print(list2)  # [[0], [0]]

此时,我们发现 list2 发生之前相同的问题。我们打印此时 list2 内部元素的地址值,发现内部两个元素也指向了同一个对象。

ele = []
list2 = [ele for _ in range(2)]

print(list(map(id, list2)))  # [1849845272832, 1849845272832]

造成问题出现的原因是,list2 的生成代码做了如下改变:

list2 = [[] for _ in range(2)]

变为了

ele = []
list2 = [ele for _ in range(2)]

list2 = [[] for _ in range(2)] 给了我们一种错觉,似乎这种方式可以产生新的对象,但是实际上,列表推导式只是一种语法糖,它只是对 for 循环的写法上的简化,你可以认为列表推导式:

list2 = [[] for _ in range(2)]

等价于 

list2 = []
for _ in range(2):
    list2.append([])

其中 [] 其实是一种动作,表示:创建一个空列表,比如:

  • list2 = [],表示创建一个空列表后,赋值给 list2
  • list2.append([]),表示创建一个空列表后,追加到 list2 尾部

那么:

ele = []
list2 = [ele for _ in range(2)]

其实可以认为等价于

ele = []

list2 = []
for _ in range(2):
    list2.append(ele)

上面代码中

  • ele = [],表示创建了一个空列表赋值给 ele
  • list2.append(ele),表示将 ele的地址值 追加到 list2 尾部

这种方式本质和列表乘法并无区别。

总结

列表乘法 [x] * n,本质是将要元素 x 复制 n 次。

若要重复的元素 x 是不可变对象类型,则使用列表乘法后,会将元素 x 的值复制多次,最终生成的列表中的每个元素:值相同,但是不是同一个对象。

若要重复的元素 x 是可变对象类型,则使用列表乘法后,会将元素 x 的对象地址值复制多次,最终生成的列表中元素:地址值相同,都指向同一个对象。

列表推导式,本质是一种语法糖,它只是简化了 for 循环写法。在代码理解上,我们还是应该将列表推导式当成普通 for 循环来解读。

到此这篇关于Python中列表乘法和列表推导式区别的文章就介绍到这了,更多相关Python列表乘法和列表推导式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 粗暴解决CUDA out of memory的问题

    粗暴解决CUDA out of memory的问题

    这篇文章主要介绍了粗暴解决CUDA out of memory的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-05-05
  • Django城市信息查询功能的实现步骤

    Django城市信息查询功能的实现步骤

    Django中的查询操作是数据库操作中一个非常重要的技术,下面这篇文章主要给大家介绍了关于Django城市信息查询功能的实现步骤,文中通过实例代码和图文介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • python命名关键字参数的作用详解

    python命名关键字参数的作用详解

    在本篇文章里小编给大家整理了一篇关于python命名关键字参数的作用详解内容,有兴趣的朋友们可以学习参考下。
    2021-03-03
  • Python检查ping终端的方法

    Python检查ping终端的方法

    今天小编就为大家分享一篇Python检查ping终端的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-01-01
  • python解决No module named pip问题两种方法

    python解决No module named pip问题两种方法

    当出现No module named pip错误时,表明您的Python环境缺少pip模块,下面这篇文章主要给大家介绍了关于python解决No module named pip问题的两种方法,需要的朋友可以参考下
    2024-01-01
  • Django values()和value_list()的使用

    Django values()和value_list()的使用

    这篇文章主要介绍了Django values()和value_list()的使用,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03
  • python中四舍五入的正确打开方式

    python中四舍五入的正确打开方式

    这篇文章主要介绍了python中四舍五入的正确打开方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • Python实现高分辨率图像导航的代码

    Python实现高分辨率图像导航的代码

    高分辨率图像导航是一种技术,它允许用户在大型图像中进行导航和浏览,而无需加载整个图像到内存中,在本文中,我们将使用30行Python代码实现这一功能,我们将使用Python的图像处理库和计算机视觉库来加载图像数据并生成高分辨率图像导航
    2024-03-03
  • Python可视化绘制图表的教程详解

    Python可视化绘制图表的教程详解

    python 有许多可视化工具,但本文主要为大家介绍一下Matplotlib。Matplotlib是一种2D的绘图库,它可以支持硬拷贝和跨系统的交互,感兴趣的可以了解一下
    2022-10-10
  • windows下python安装小白入门教程

    windows下python安装小白入门教程

    这篇文章主要为大家详细介绍了windows下python安装小白入门教程,文中安装步骤介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-09-09

最新评论