Python列表嵌套常见坑点及解决方案


Posted in Python onSeptember 30, 2020

1.嵌套列表

Python中有一种内置的数据类型叫列表(list),它是一种容器,可以用来承载其他的对象(准确的说是其他对象的引用),列表中的对象可以称为列表的元素,很明显我们可以把列表作为列表中的元素,这就是所谓的嵌套列表。

嵌套列表可以模拟出现实中的表格、矩阵、2D游戏的地图(如植物大战僵尸的花园)、棋盘(如国际象棋、黑白棋)等。

2.识别坑点

在使用嵌套的列表时要小心,否则很可能遭遇非常尴尬的情况,下面是一个小例子。

def main():  names = ['关羽', '张飞', '赵云', '马超', '黄忠']  subjs = ['语文', '数学', '英语']  scores = [[0] * 3] * 5  for row, name in enumerate(names):    print('请输入%s的成绩' % name)    for col, subj in enumerate(subjs):      scores[row][col] = float(input(subj + ': '))  print(scores)if __name__ == '__main__':  main()
  names = ['关羽', '张飞', '赵云', '马超', '黄忠']
  subjs = ['语文', '数学', '英语']
  scores = [[0] * 3] * 5
  for row, name in enumerate(names):
    print('请输入%s的成绩' % name)
    for col, subj in enumerate(subjs):
      scores[row][col] = float(input(subj + ': '))
  print(scores)
if __name__ == '__main__':
  main()

我们希望录入5个学生3门课程的成绩,于是定义了一个有5个元素的列表,而列表中的每个元素又是一个由3个元素构成的列表,这样一个列表的列表刚好跟一个表格是一致的,相当于有5行3列。

接下来我们通过嵌套的for-in循环输入每个学生3门课程的成绩。程序执行完成后我们发现,每个学生3门课程的成绩是一模一样的(尴尬),而且就是最后录入的那个学生的成绩。

3。区分两个概念

要想把这个坑填平,我们首先要区分对象和对象的引用这两个概念,而要区分这两个概念,还得先说说内存中的栈和堆。

我们经常会听人说起“堆栈”这个词,但实际上“堆”和“栈”是两个不同的概念。众所周知,一个程序运行时需要占用一些内存空间来存储数据和代码,那么这些内存从逻辑上又可以做进一步的划分。

对底层语言(如C语言)有所了解的程序员大都知道,程序中可以使用的内存从逻辑上可以为五个部分,按照地址从高到低依次是:栈(stack)、堆(heap)、数据段(data segment)、只读数据段(static area)和代码段(code segment)。

栈用来存储局部、临时变量,以及函数调用时保存现场和恢复现场需要用到的数据,这部分内存在代码块开始执行时自动分配,代码块执行结束时自动释放,通常由编译器自动管理。

堆的大小不固定,可以动态的分配和回收,因此如果程序中有大量的数据需要处理,这些数据通常都放在堆上,如果堆空间没有正确的被释放会引发内存泄露的问题,而像Python、Java等编程语言都使用了垃圾回收机制来实现自动化的内存管理(自动回收不再使用的堆空间)。

4。小例子

所以,下面的代码中,变量a并不是真正的对象,它是对象的引用,相当于记录了对象在堆空间的地址,通过这个地址我们可以访问到对应的对象。

a = object()b = ['apple', 'pitaya', 'grape']
b = ['apple', 'pitaya', 'grape']

同理,变量b是列表容器的引用,它引用了堆空间上的列表容器,而列表容器中并没有保存真正的对象,它保存的也仅仅是对象的引用。

知道了这一点,我们可以回过头看看刚才的程序,我们对列表进行[[0]* 3] * 5操作时,仅仅是将[0, 0, 0] 这个列表的地址进行了复制,并没有创建新的列表对象。

所以,容器中虽然有5个元素,但是这5个元素引用了同一个列表对象。这一点可以通过id函数检查scores[0]和scores[1]的地址得到证实。在此我们举一个小例子,读者朋友们可以敲一敲加深印象。

a = [[0]*3]*5id(a[0])id(a[1])# id相等
id(a[1])
# id相等

5。正确代码

所以,正确的代码应该按照如下的方式进行修改。

def main():  names = ['关羽', '张飞', '赵云', '马超', '黄忠']  subjs = ['语文', '数学', '英语']  scores = [[]] * 5  for row, name in enumerate(names):    print('请输入%s的成绩' % name)    scores[row] = [0] * 3 #变为不再嵌套    for col, subj in enumerate(subjs):      scores[row][col] = float(input(subj + ': '))  print(scores)if __name__ == '__main__':  main()'关羽', '张飞', '赵云', '马超', '黄忠']
  subjs = ['语文', '数学', '英语']
  scores = [[]] * 5
  for row, name in enumerate(names):
    print('请输入%s的成绩' % name)
    scores[row] = [0] * 3 #变为不再嵌套
    for col, subj in enumerate(subjs):
      scores[row][col] = float(input(subj + ': '))
  print(scores)
if __name__ == '__main__':
  main()

或者

def main():  names = ['关羽', '张飞', '赵云', '马超', '黄忠']  subjs = ['语文', '数学', '英语']  scores = [[0] * 3 for _ in range(5)]  for row, name in enumerate(names):    print('请输入%s的成绩' % name)    scores[row] = [0] * 3    for col, subj in enumerate(subjs):      scores[row][col] = float(input(subj + ': '))  print(scores)if __name__ == '__main__':  main()
  names = ['关羽', '张飞', '赵云', '马超', '黄忠']
  subjs = ['语文', '数学', '英语']
  scores = [[0] * 3 for _ in range(5)]
  for row, name in enumerate(names):
    print('请输入%s的成绩' % name)
    scores[row] = [0] * 3
    for col, subj in enumerate(subjs):
      scores[row][col] = float(input(subj + ': '))
  print(scores)
if __name__ == '__main__':
  main()

以上就是使用嵌套列表需要注意的问题及解决措施,希望大家多多总结,以此避免在使用嵌套列表或者复制对象时可能遇到的坑。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python检查字符串是否是正确ISBN的方法
Jul 11 Python
使用Python设计一个代码统计工具
Apr 04 Python
网红编程语言Python将纳入高考你怎么看?
Jun 07 Python
Python3单行定义多个变量或赋值方法
Jul 12 Python
Python嵌套式数据结构实例浅析
Mar 05 Python
django drf框架中的user验证以及JWT拓展的介绍
Aug 12 Python
python读写Excel表格的实例代码(简单实用)
Dec 19 Python
IntelliJ 中配置 Anaconda的过程图解
Jun 01 Python
python编写一个会算账的脚本的示例代码
Jun 02 Python
python3中celery异步框架简单使用+守护进程方式启动
Jan 20 Python
PyQt5通过信号实现MVC的示例
Feb 06 Python
python urllib库的使用详解
Apr 13 Python
python实现感知机模型的示例
Sep 30 #Python
python 实现关联规则算法Apriori的示例
Sep 30 #Python
Python之字典添加元素的几种方法
Sep 30 #Python
Python之字典对象的几种创建方法
Sep 30 #Python
python 实现朴素贝叶斯算法的示例
Sep 30 #Python
Python字典取键、值对的方法步骤
Sep 30 #Python
Python根据字典的值查询出对应的键的方法
Sep 30 #Python
You might like
PHP下常用正则表达式整理
2010/10/26 PHP
thinkphp控制器调度使用示例
2014/02/24 PHP
PHP使用适合阅读的格式显示文件大小的方法
2015/03/05 PHP
yii2安装详细流程
2018/05/23 PHP
jquery 插件开发方法小结
2009/10/23 Javascript
js图片自动切换效果处理代码
2013/05/07 Javascript
解决css和js的{}与smarty定界符冲突问题的两种方法
2013/09/10 Javascript
配置Grunt的Task时通配符支持和动态生成文件名问题
2015/09/06 Javascript
MVC+jQuery.Ajax异步实现增删改查和分页
2020/12/22 Javascript
jQuery+Ajax+PHP弹出层异步登录效果(附源码下载)
2016/05/27 Javascript
AngularJS基于ngInfiniteScroll实现下拉滚动加载的方法
2016/12/14 Javascript
详解Angular2表单-模板驱动的表单(Template-Driven Forms)
2017/08/04 Javascript
Vue精简版风格概述
2018/01/30 Javascript
bing Map 在vue项目中的使用详解
2018/04/09 Javascript
vue实现element-ui对话框可拖拽功能
2018/08/17 Javascript
解决layui下拉框监听问题(监听不到值的变化)
2019/09/28 Javascript
[30:00]完美世界DOTA2联赛PWL S2 Rebirth vs LBZS 第二场 11.28
2020/12/01 DOTA
微信 用脚本查看是否被微信好友删除
2016/10/28 Python
python3 模拟登录v2ex实例讲解
2017/07/13 Python
对django 模型 unique together的示例讲解
2019/08/06 Python
Python+OpenCV+图片旋转并用原底色填充新四角的例子
2019/12/12 Python
Python内建序列通用操作6种实现方法
2020/03/26 Python
Python爬虫requests库多种用法实例
2020/05/28 Python
Python爬虫设置Cookie解决网站拦截并爬取蚂蚁短租的问题
2021/02/22 Python
你所知道的集合类都有哪些?主要方法?
2012/12/31 面试题
美术教师自我鉴定
2014/02/12 职场文书
院领导写的就业推荐信
2014/03/09 职场文书
2014年化验员工作总结
2014/11/18 职场文书
2014年后勤管理工作总结
2014/12/01 职场文书
幼儿园中班教师个人总结
2015/02/05 职场文书
4S店销售内勤岗位职责
2015/04/13 职场文书
环保建议书范文
2015/09/14 职场文书
2016优秀护士先进个人事迹材料
2016/02/25 职场文书
导游词之晋城蟒河
2019/12/12 职场文书
2021年最新用于图像处理的Python库总结
2021/06/15 Python
分布式架构Redis中有哪些数据结构及底层实现原理
2022/03/13 Redis