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交互式图形编程实例(三)
Nov 17 Python
pandas.DataFrame 根据条件新建列并赋值的方法
Apr 08 Python
20行python代码实现人脸识别
May 05 Python
Django Form 实时从数据库中获取数据的操作方法
Jul 25 Python
Python Subprocess模块原理及实例
Aug 26 Python
Python socket模块方法实现详解
Nov 05 Python
Python实现图像去噪方式(中值去噪和均值去噪)
Dec 18 Python
Pycharm+Python工程,引用子模块的实现
Mar 09 Python
python爬虫学习笔记之pyquery模块基本用法详解
Apr 09 Python
浅析python函数式编程
Sep 26 Python
Python基于内置函数type创建新类型
Oct 22 Python
Python自然语言处理之切分算法详解
Apr 25 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
通用PHP动态生成静态HTML网页的代码
2010/03/04 PHP
PHP制作万年历
2015/01/07 PHP
Laravel框架实现model层的增删改查(CURD)操作示例
2018/05/12 PHP
详解laravel安装使用Passport(Api认证)
2018/07/27 PHP
ajax 文件上传应用简单实现
2009/03/03 Javascript
跟着JQuery API学Jquery 之三 筛选
2010/04/09 Javascript
JS限制上传图片大小不使用控件在本地实现
2012/12/19 Javascript
JS中批量给元素绑定事件过程中的相关问题使用闭包解决
2013/04/15 Javascript
jQuery中scrollLeft()方法用法实例
2015/01/16 Javascript
JavaScript中操作Mysql数据库实例
2015/04/02 Javascript
深入解析jQuery中Deferred的deferred.promise()方法
2016/05/03 Javascript
jquery制做精致的倒计时特效
2016/06/13 Javascript
jQuery组件easyui基本布局实现代码
2016/08/25 Javascript
JavaScript 用fetch 实现异步下载文件功能
2017/07/21 Javascript
js+html获取系统当前时间
2017/11/10 Javascript
微信小程序获取音频时长与实时获取播放进度问题
2018/08/28 Javascript
JavaScript设计模式之代理模式实例分析
2019/01/16 Javascript
JavaScript获取某一天所在的星期
2019/09/05 Javascript
原生js实现弹幕效果
2020/11/29 Javascript
手动实现vue2.0的双向数据绑定原理详解
2021/02/06 Vue.js
提升Python程序运行效率的6个方法
2015/03/31 Python
详解Python中的__new__、__init__、__call__三个特殊方法
2016/06/02 Python
在python中以相同顺序shuffle两个list的方法
2018/12/13 Python
python实现五子棋小游戏
2020/03/25 Python
Python入门Anaconda和Pycharm的安装和配置详解
2019/07/16 Python
Python selenium文件上传下载功能代码实例
2020/04/13 Python
Daniel Wellington官方海外旗舰店:丹尼尔惠灵顿DW手表
2018/02/22 全球购物
新领导上任欢迎词
2014/01/13 职场文书
公司户外活动总结
2014/07/04 职场文书
三关爱志愿服务活动方案
2014/08/17 职场文书
司机工作自我鉴定
2014/09/19 职场文书
医德医风自我评价2015
2015/03/03 职场文书
2015年感恩父亲节演讲稿
2015/03/19 职场文书
2015年双拥工作总结
2015/04/08 职场文书
实习证明模板
2015/06/16 职场文书
Java面试题冲刺第十八天--Spring框架3
2021/08/07 面试题