Python 避免字典和元组的多重嵌套问题


Posted in Python onJuly 15, 2022

一、字典、元组的多重嵌套

例 1:记录全班学生的成绩。

分析:定义一个 SimpleGradebook类,

学生名是字典self._grades的键,成绩是字典self._grades的值。

class SimpleGradebook():
    def __init__(self):
        self._grades = {}
    def add_student(self, name):
        self._grades[name] = []
    def report_grade(self, name, score):
        self._grades[name].append(score)
    def average_grade(self, name):
        grades = self._grades[name]
        return self._grades, sum(grades) / len(grades)
book = SimpleGradebook()
book.add_student('qinlu')
book.report_grade('qinlu', 99)
print(book.average_grade('qinlu'))
({'qinlu': [99]}, 99.0)

字典可能因为功能过多导致结果多重嵌套。

例 2:扩充 SimpleGradebook类,按科目保存成绩。

分析:定义一个 BySubjectGradebook类,字典by_subject嵌套在字典self._grades内。

学生名是字典self._grades的键,科目、成绩是self._grades的值。

科目是字典by_subject的键,成绩是字典by_subject的值。

class BySubjectGradebook():
    """
        report_grade(), average_grade()嵌套了两层的字典
    """
    def __init__(self):
        self._grades = {}
    def add_student(self, name):
        self._grades[name] = {}
    def report_grade(self, name, subject, score):
        by_subject = self._grades[name]
        grade_list = by_subject.setdefault(subject, [])
        grade_list.append(score)
    def average_grade(self, name):
        by_subject = self._grades[name]
        total, count = 0, 0
        for scores in by_subject.values():
            total += sum(scores)
            count += len(scores)
        return self._grades, total / count
book = BySubjectGradebook()
book.add_student('qinlu')
book.report_grade('qinlu', 'Math', 99)
book.report_grade('qinlu', 'Math', 88)
book.report_grade('qinlu', 'Computer', 90)
book.report_grade('qinlu', 'Computer', 80)
print(book.average_grade('qinlu'))
({'qinlu': {'Math': [99, 88], 'Computer': [90, 80]}}, 89.25)

例 3:需求变更,需记录每次成绩占总成绩的权重。(期中、期末考试所占的分量比随堂考大)

class WeightedGradebook():
    def __init__(self):
        self._grades = {}
    def add_student(self, name):
        self._grades[name] = {}
    def report_grade(self, name, subject, score, weight):
        by_subject = self._grades[name]
        grade_list = by_subject.setdefault(subject, [])
        grade_list.append(score, weight)
    def average_grade(self, name):
        by_subject = self._grades[name]
        score_sum, score_count = 0, 0
        for subject, scores in by_subject.items():
            subject_avg, total_weight = 0, 0
            for score, weight in scores:
                #...
        return score_sum / score_count

该代码出现字典、元组的多层嵌套,应拆解为类。多层嵌套的代码,很难维护。

二、嵌套结构重构为类

将下面的字典重构为类。

字典by_subject嵌套在字典self._students内。

{'qinlu': {'Math': [(99, 0.1), (88, 0.9)], 'Computer': [(90. 0.1), (80, 0.9)]}}

分析:

① Gradebook()类,学生名是字典self._students的键;科目、成绩、权重是self._grades的值。

② Student()类,科目是字典self._subjects的键;成绩、权重是self._subjects的值。

③ Subject()类,成绩是列表self._grades的第一位;权重是列表self._grades的第二位。

从最底层开始重构,即考试成绩。这么简单的信息,没必要写成类。

namedtuple()命名元组。

'''
学习中遇到问题没人解答?小编创建了一个Python学习交流群:711312441
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
from collections import namedtuple

Grade = namedtuple('Grade', ('score', 'weight'))

# 科目类,该类包含考试成绩
class Subject():
    def __init__(self):
        self._grades = []
    def report_grade(self, score, weight):
        self._grades.append(Grade(score, weight))
    def average_grade(self):
        total, total_weight = 0, 0
        # print(self._grades)
        for grade in self._grades:
            # print(grade)
            total += grade.score * grade.weight
            total_weight += grade.weight
        return total / total_weight

# 学生类,该类包含学习课程
class Student():
    def __init__(self):
        self._subjects = {}
    def subject(self, name):
        if name not in self._subjects:
            self._subjects[name] = Subject()
        return self._subjects[name]
    def average_grade(self):
        total, count = 0, 0
        for subject in self._subjects.values():
            total += subject.average_grade()
            count += 1
        return total / count

# 成绩册类,包含所有学生考试成绩的容器类,该容器类以学生名字为键,可动态添加学生
class Gradebook():
    def __init__(self):
        self._students = {}
    def student(self, name):
        if name not in self._students:
            self._students[name] = Student()
        return self._students[name]

book = Gradebook()
qin = book.student('qinlu')
math = qin.subject('Math')
math.report_grade(99, 0.1)
math.report_grade(88, 0.9)
print(qin.average_grade())
89.1

虽然代码量是原来的两倍,但更清晰,更易扩展,理解起来比原来容易。

到此这篇关于Python 避免字典和元组的多重嵌套的文章就介绍到这了,更多相关Python 多重嵌套内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python字典值排序并取出前n个key值的方法
Oct 17 Python
python简易实现任意位数的水仙花实例
Nov 13 Python
django框架防止XSS注入的方法分析
Jun 21 Python
python实现连连看辅助(图像识别)
Mar 25 Python
在django中图片上传的格式校验及大小方法
Jul 28 Python
python matplotlib饼状图参数及用法解析
Nov 04 Python
Python Django中间件,中间件函数,全局异常处理操作示例
Nov 08 Python
Python 实现将数组/矩阵转换成Image类
Jan 09 Python
如何使用 Python 读取文件和照片的创建日期
Sep 05 Python
利用python实现汉诺塔游戏
Mar 01 Python
一篇文章带你搞懂Python类的相关知识
May 20 Python
浅析Python实现DFA算法
Jun 26 Python
Pytorch中expand()的使用(扩展某个维度)
Jul 15 #Python
Python实现聚类K-means算法详解
Jul 15 #Python
python自动获取微信公众号最新文章的实现代码
Jul 15 #Python
pytorch实现加载保存查看checkpoint文件
Jul 15 #Python
pytest实现多进程与多线程运行超好用的插件
Jul 15 #Python
python如何将mat文件转为png
Jul 15 #Python
python读取mat文件生成h5文件的实现
Jul 15 #Python
You might like
Fine Uploader文件上传组件应用介绍
2013/01/06 PHP
php获取、检查类名、函数名、方法名的函数方法
2015/06/25 PHP
Yii数据库缓存实例分析
2016/03/29 PHP
laravel 框架实现无限级分类的方法示例
2019/10/31 PHP
javascript入门·图片对象(无刷新变换图片)\滚动图像
2007/10/01 Javascript
使用JavaScript检测Firefox浏览器是否启用了Firebug的代码
2010/12/28 Javascript
JavaScript高级程序设计 错误处理与调试学习笔记
2011/09/10 Javascript
使用Java实现简单的server/client回显功能的方法介绍
2013/05/03 Javascript
jQuery插件Easyui设置datagrid的pageNumber导致两次请求问题的解决方法
2016/08/06 Javascript
easyui datagrid 大数据加载效率慢,优化解决方法(推荐)
2016/11/09 Javascript
你有必要知道的10个JavaScript难点
2017/07/25 Javascript
在一般处理程序(ashx)中弹出js提示语
2017/08/16 Javascript
BetterScroll 在移动端滚动场景的应用
2017/09/18 Javascript
如何在JavaScript中优雅的提取循环内数据详解
2019/03/04 Javascript
js实现GIF动图分解成多帧图片上传
2019/10/24 Javascript
vue中keep-alive,include的缓存问题
2019/11/26 Javascript
jQuery模仿ToDoList实现简单的待办事项列表
2019/12/30 jQuery
[07:59]2014DOTA2叨叨刀塔 林熊猫称被邀请赛现场盛况震撼
2014/07/21 DOTA
Python模块学习 filecmp 文件比较
2012/08/27 Python
Python操作SQLite数据库的方法详解【导入,创建,游标,增删改查等】
2017/07/11 Python
Python xlwt设置excel单元格字体及格式
2020/04/18 Python
如何在python字符串中输入纯粹的{}
2018/08/22 Python
python assert的用处示例详解
2019/04/01 Python
python小技巧——将变量保存在本地及读取
2020/11/13 Python
凯伦·米莲女装网上商店:Karen Millen
2017/11/07 全球购物
同步和异步有何异同,在什么情况下分别使用他们?
2012/12/28 面试题
高中生学习生活的自我评价
2013/11/27 职场文书
《唯一的听众》教学反思
2014/02/20 职场文书
环保建议书600字
2014/05/14 职场文书
会计求职信
2014/05/29 职场文书
校友回访母校寄语
2015/02/26 职场文书
学习党章心得体会2016
2016/01/15 职场文书
教你使用一行Python代码玩遍童年的小游戏
2021/08/23 Python
python脚本框架webpy的url映射详解
2021/11/20 Python
Python编程中内置的NotImplemented类型的用法
2022/03/23 Python
经典《舰娘》游改全新动画预告 预定11月开播
2022/04/01 日漫