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网络编程实例简析
Sep 26 Python
详解Python的Django框架中manage命令的使用与扩展
Apr 11 Python
python导入模块交叉引用的方法
Jan 19 Python
Python查找最长不包含重复字符的子字符串算法示例
Feb 13 Python
Django 接收Post请求数据,并保存到数据库的实现方法
Jul 12 Python
python安装scipy的步骤解析
Sep 28 Python
pytorch 自定义卷积核进行卷积操作方式
Dec 30 Python
TensorBoard 计算图的查看方式
Feb 15 Python
Python实现多线程下载脚本的示例代码
Apr 03 Python
深入理解Python变量的数据类型和存储
Feb 01 Python
Python第三方库安装缓慢的解决方法
Feb 06 Python
自己搭建resnet18网络并加载torchvision自带权重的操作
May 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/05/20 PHP
PHP CURL获取返回值的方法
2014/05/04 PHP
微信公众平台网页授权获取用户基本信息中授权回调域名设置的变动
2014/10/21 PHP
对YUI扩展的Gird组件 Part-1
2007/03/10 Javascript
Jquery 实现Tab效果 思路是js思路
2010/03/02 Javascript
精通Javascript系列之数值计算
2011/06/07 Javascript
关于URL中的特殊符号使用介绍
2011/11/03 Javascript
20行代码实现的一个CSS覆盖率测试脚本
2013/07/07 Javascript
JS中typeof与instanceof之间的区别总结
2013/11/14 Javascript
Javascript单元测试框架QUnitjs详细介绍
2014/05/08 Javascript
javascript实现禁止复制网页内容
2014/12/16 Javascript
一篇文章掌握RequireJS常用知识
2016/01/26 Javascript
超实用的javascript时间处理总结
2016/08/16 Javascript
基于JS实现发送短信验证码后的倒计时功能(无视页面刷新,页面关闭不进行倒计时功能)
2016/09/02 Javascript
JavaScript获取URL中参数querystring的方法详解
2016/10/11 Javascript
jQuery实现的无缝广告图片左右滚动功能详解
2016/12/24 Javascript
利用nginx + node在阿里云部署https的步骤详解
2017/12/19 Javascript
通过cordova将vue项目打包为webapp的方法
2019/02/02 Javascript
react中使用css的7中方式(最全总结)
2019/02/11 Javascript
vue项目中常见问题及解决方案(推荐)
2019/10/21 Javascript
jQuery实现鼠标滑动切换图片
2020/05/27 jQuery
Vue组件为什么data必须是一个函数
2020/06/11 Javascript
完美解决通过IP地址访问VUE项目的问题
2020/07/18 Javascript
[02:40]DOTA2英雄基础教程 炼金术士
2013/12/23 DOTA
[56:21]LGD vs IG 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
python自动zip压缩目录的方法
2015/06/28 Python
Anaconda2 5.2.0安装使用图文教程
2018/09/19 Python
Python中常用的8种字符串操作方法
2019/05/06 Python
python中doctest库实例用法
2020/12/31 Python
德国黑胶唱片、街头服装及运动鞋网上商店:HHV
2018/08/24 全球购物
Ibatis中如何提高SQL Map的性能
2013/05/11 面试题
2014年学校党建工作汇报材料
2014/11/02 职场文书
2014年信息宣传工作总结
2014/12/18 职场文书
通知格式
2015/04/27 职场文书
经典哲理警句:志不真则心不热,心不热则功不贤
2019/11/14 职场文书
Java Socket实现多人聊天系统
2021/07/15 Java/Android