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连接DB2数据库
Aug 27 Python
Python实现将一个正整数分解质因数的方法分析
Dec 14 Python
PyCharm 常用快捷键和设置方法
Dec 20 Python
利用 python 对目录下的文件进行过滤删除
Dec 27 Python
python3 图片referer防盗链的实现方法
Mar 12 Python
django orm 通过related_name反向查询的方法
Dec 15 Python
Django REST framework 如何实现内置访问频率控制
Jul 23 Python
详解一种用django_cache实现分布式锁的方式
Sep 01 Python
解决python web项目意外关闭,但占用端口的问题
Dec 17 Python
Python实现使用dir获取类的方法列表
Dec 24 Python
tensorflow 实现从checkpoint中获取graph信息
Feb 10 Python
python神经网络编程实现手写数字识别
May 27 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学习笔记(三)操作符与控制结构
2011/08/06 PHP
php启用sphinx全文搜索的实现方法
2014/12/24 PHP
CentOS下PHP安装Oracle扩展
2015/02/15 PHP
解决windows上php xdebug 无法调试的问题
2020/02/19 PHP
JavaScript脚本性能的优化方法
2007/02/02 Javascript
DOM操作一些常用的属性汇总
2015/03/13 Javascript
JS制作简单的三级联动
2015/03/18 Javascript
详解Bootstrap的aria-label和aria-labelledby应用
2016/01/04 Javascript
JavaScript中各种引用类型的常用操作方法小结
2016/05/05 Javascript
jQuery实现手机版页面翻页效果的简单实例
2016/10/05 Javascript
easyUI实现(alert)提示框自动关闭的实例代码
2016/11/07 Javascript
js获取当前时间(昨天、今天、明天)
2016/11/23 Javascript
Underscore之Array_动力节点Java学院整理
2017/07/10 Javascript
微信小程序通过保存图片分享到朋友圈功能
2018/05/24 Javascript
微信小程序实现卡片层叠滑动效果
2019/06/21 Javascript
vue-cli和v-charts实现可视化图表过程解析
2019/10/08 Javascript
vue 组件之间事件触发($emit)与event Bus($on)的用法说明
2020/07/28 Javascript
在DigitalOcean的服务器上部署flaskblog应用
2015/12/19 Python
怎样使用Python脚本日志功能
2016/08/14 Python
Python可变参数*args和**kwargs用法实例小结
2018/04/27 Python
python3 对list中每个元素进行处理的方法
2018/06/29 Python
python 进程间数据共享multiProcess.Manger实现解析
2019/09/23 Python
python selenium 执行完毕关闭chromedriver进程示例
2019/11/15 Python
python 解决print数组/矩阵无法完整输出的问题
2020/02/19 Python
Skyscanner英国:苏格兰的全球三大领先航班搜索服务之一
2017/11/09 全球购物
开学典礼主持词
2014/03/19 职场文书
企业道德讲堂实施方案
2014/03/19 职场文书
开工仪式主持词
2014/03/20 职场文书
公司年底活动方案
2014/08/17 职场文书
整顿机关作风心得体会
2014/09/10 职场文书
群众路线党员自我评议范文2014
2014/09/24 职场文书
2014国庆节国旗下演讲稿(精选版)
2014/09/26 职场文书
共产党员批评与自我批评
2014/10/15 职场文书
2014年党风建设工作总结
2014/11/19 职场文书
2015民办小学年度工作总结
2015/05/26 职场文书
二婚主持词
2015/06/30 职场文书