《编程导论》8.3 类和继承(接8.2.2)(辅助学习的笔记~)

这一篇接着上篇8.2.2的内容讲述同一个实例

#8.3_Encapsulation and information hiding(封装和信息隐藏)

class Grades(object):
    """学生到成绩列表的映射关系"""
    def __init__(self):
        """创建一个空的成绩册"""
        self.students = []
        self.grades = {}
        self.isSorted = True

    def addStudent(self,student):
        """假定student的类型是Student
            把student添加到成绩册里"""
        if student in self.students:
            raise ValueError('Duplicate student')
        self.students.append(student)
        self.grades[student.getIdNum()] = []
        self.isSorted = False

    def addGrade(self, student, grade):
        """假定成绩是浮点数
            把成绩添加到对应学生的成绩册上"""
        try:
            self.grades[student.getIdNum()].append(grade)
        except:
            raise ValueError('Student not in mapping')

    def getGrades(self, student):
        """返回学生的成绩列表"""
        try:#返回学生成绩的拷贝
            return self.grades[student.getIdNum()][:]
        except:
            raise ValueError('Student not in mapping')

    def getStudents(self):
        """返回成绩册中的学生列表"""
        if not self.isSorted:
            self.students.sort()
            self.isSorted = True
        return self.students[:]#返回学生列表的副本
        #此处暂时忽略,8.3.1_生成器再回头注释上一句代码,使用以下代码
        #for s in self.students:
            #yield s
        
    #返回副本会导致额外性能开销,但是直接返回实例变量进行赋值则会副作用:
    #修改赋值的时候也会修改原值
    #如:
    #allStudents = course1.getStudents()
    #allStudents.extend(course2.getStudents())

def gradeReport(course):
    """假定course类型为Grades"""
    report = ''
    for s in course.getStudents():
        tot = 0.0
        numGrades = 0
        for g in course.getGrades(s):
            tot += g
            numGrades += 1
        try:
            average = tot/numGrades
            report = report + '\n'\
                     + str(s) + '\'s mean grade is ' + str(average)
        except ZeroDivisionError:
            report = report + '\n'\
                     + str(s) + ' has no grades'
    return report

ug1 = UG('Jane Doe', 2014)
ug2 = UG('John Doe', 2015)
ug3 = UG('David Henry', 2003)
g1 = Grad('Billy Buckner')
g2 = Grad('Bucky F. Dent')
sixHundred = Grades()
sixHundred.addStudent(ug1)
sixHundred.addStudent(ug2)
sixHundred.addStudent(g1)
sixHundred.addStudent(g2)
for s in sixHundred.getStudents():
    sixHundred.addGrade(s, 75)
sixHundred.addGrade(g1, 25)
sixHundred.addGrade(g2, 100)
sixHundred.addStudent(ug3)
print(gradeReport(sixHundred))

#面向对象编程的两大核心概念:封装和信息隐藏

#如:Rafael = MITPerson()
#封装把数据属性和操作方法封装在一起,使用时就可以通过赋值创建新的实例
#并通过点标记法Rafael.getIdNum()进行访问该实例的属性,如学号、年龄。

#信息隐藏则是程序员隐藏数据属性的可见性,用户只能通过规范的类方法来访问数据
#举例说明就是,Rafael的idNum属性只能通过Rafael.getIdNum()来访问,而非Rafael.idNum

#这在Java和C++中是可以强制隐藏的,而python则没有,仍然可以用Rafael.idNum直接访问
#甚至,python还允许进行写操作,如Rafael.birtday = '8/7/2001'(在外部将Person的实例变量给赋值)
#和允许外部创建实例变量,如me.age = Rafael.getAge()(age是Person本没有的实例变量)

#信息隐藏的好处在于程序员可以随意修改类的具体实现,而不怕破坏用户的代码
#因此需要python程序员遵守规则,不在类的外部直接访问数据属性

附加对生成器的简要理解~

#8.3.1_Generator(生成器)_使大容量数据处理更有效率!

"""yield语句是类似于return语句但也十分不一样,含有它的函数一般被称为生成器函数"""

"""简单来说他们的区别在于,例子中return会返回一整个列表,来进行下一步的操作
    而yield则通过for循环的搭配使用,逐个迭代每个需要下一步操作的值
    即迭代列表里的一个元素,然后把for循环挂起跳出,完成之后的操作后再回到for循环
    回到原来的位置迭代下一个元素,同理继续操作"""

"""这里的好处在于,传统的函数返回一整个列表,当这个列表的容量很大的时候,所占的内存就会很大,
    严重影响性能;而生成器函数每次返回列表中的一个元素进行操作,内存极小,还可以再回到原位置,
    继续迭代下一个元素继续操作,性能和效率上优劣之分就很明显了。"""

#可以回看getStudents函数,用以下程序测试一下
import time

t1 = time.time()
book = Grades()
book.addStudent(Grad('Julie'))
book.addStudent(Grad('Charlie'))
for s in book.getStudents():
    print(s)
t2 = time.time()
print(t2 - t1)   #用于测试运行速度
#可以看看这里,有更深的了解噢~https://blog.csdn.net/S_o_l_o_n/article/details/81878032

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值