Python学习笔记-面向对象的程序设计

面向过程的程序设计的步骤:

  1. 清楚地分析程序从输入到输出的各个步骤
  2. 按照程序执行过程从前到后编写各个步骤,采用调用的方式将各步骤组织起来
  3. 在编写过程中,将高耦合部分封装成模块或函数,尽量实现模块化设计
  4. 输入参数,按照程序执行过程开展调试
    基本思想:将任务分解成特定的功能模块,再将功能模块按照运行步骤组织起来。
    主要用于一般程序,不适用于大型软件的开发。

面向对象的程序设计

对象的两种特征:状态和行为
基本步骤:

  1. 根据功能,抽象出业务对象。
  2. 对需求进行合理分层,构建相对独立的业务模块,设计业务逻辑,并围绕对象利用封装、继承、多态等基本设计方法,抽象业务需求。
  3. 在编写过程中,利用对象之间的关系组织功能需求。
  4. 以对象为单位输入参数、开展测试。

对类和对象的抽象:即通过功能划分将业务逻辑分解成相对独立的功能体,将业务逻辑组织为对象间的关系

寻找最高GPA

#gpa.py  GPA最高的那个学生
class Student:#创建一个学生类,记录一个学生的信息(姓名、总学分、总绩点)
    def __init__(self,name,hours,qpoints):#构造函数,定义对象的各个属性,self:类对象变量
        self.name=name
        self.hours=float(hours)
        self.qpoints=float(qpoints)
        #将hours和qpoint强制转换为浮点型,便于乘除法运算
        
    def getName(self):#获取学生姓名信息
        return self.name
    
    def getHours(self):#获取学生总学分信息
        return self.hours
    
    def getQpoints(self):#获取学生绩点信息
        return self.qpoints
    
    def gpa(self):#获取学生的平均绩点
        return self.qpoints/self.hours
        
 def makeStudent(inforStr):#设inforStr为此函数的对象变量
    #返回学生对象
    name,hours,qpoints=inforStr.split(",")
    #将输入的变量,通过,分割为3分,分别赋给name,houes,qpoints
    return Student(name,hours,qpoints)#调用Student类,并将分割得到的数据赋给此类
    
 def main():
    filename=raw_input("Enter name the grade file:")#输入存放数据文件的文件名
    infile=open(filename,'r')#以只读的方式打开文件
    best=makeStudent(infile.readline())#将文件的第一行记录赋给变量best
    #设置文件中的第一行记录为best
    for line in infile:#处理文件的剩余行数据
        s=makeStudent(line)#将文件的其他行记录赋给变量s
    #将每一行数据转换为一个记录
        if s.gpa()>best.gpa():#如果该学生是目前GPA记录最高的,则记录下来
            best=s
    infile.close()#关闭文件连接
    print("The best student is:",best.getName())
    print("hours:",best.getHours())
    print("GPA:",best.gpa())
    #打印最高GPA学生信息
    
 if __name__=='__main__':
    main()
#一般用来测试模块功能的,只有直接运行[python 模块.py]的时候才会运行这个

返回所有平均绩点最高的学生信息:

def main():
    filename=raw_input("Enter name the grade file:")#输入存放数据文件的文件名
    infile=open(filename,'r')#以只读的方式打开文件
    best=makeStudent(infile.readline())#将文件的第一行记录赋给变量best
    a=[]#初始化列表a
    a.append(best.getName())
    a.append(best.getHours())
    a.append(best.gpa())#分别将第一行记录的名字,总学分和GPA加入列表
    #设置文件中的第一行记录为best
    for line in infile:#处理文件的剩余行数据
        s=makeStudent(line)#将文件的其他行记录赋给变量s
        a.append(s.getName())
        a.append(s.getHours())
        a.append(s.gpa())#分别将记录的名字,总学分和GPA加入列表
        #将每一行数据转换为一个记录
        if s.gpa()>best.gpa():#如果该学生是目前GPA记录最高的,则记录下来
            best=s
    infile.close()#关闭文件连接
    
    for i in range(len(a)/3):#有几行记录就循环几次
        if a[2+3*1]==best.gpa():#若有学生的GPA与最高的学生相同,则输出该学生的相关信息
            print("The best student is:",a[3*i])
            print("hours:",a[1+3*i])
            print("GPA:",a[2+3*1])

只有主函数部分略有不同,这里是将所有记录都存在列表里,然后每份记录分别于最高GPA比对,若两者相同则输出。

弹道计算

IPO:

  • 输入:子弹的发射角度、初始速度、初始高度。
  • 处理:进行弹道计算,即时刻更新子弹在飞行中的位置(x,y坐标、y的速度)。
  • 输出:子弹在落地之前飞行的距离。

忽略空气阻力并且假设子弹保持在近地球表面,即水平方向上速度不变,竖直方向上重力加速度为9.8m/s。
两个问题:

  1. 子弹所处的高度,通过高度可以计算子弹什么时候落地
  2. 距离,用于跟踪子弹能飞多远
    projectile.py:
#projectile.py  追踪子弹(投射体)的飞行路线
from math import sin,cos,radians#引入math库中的sin,cos,radians(角度转弧度)函数
class Projectile:#创建一个投射体的类,即包含一些计算子弹飞行路线所需函数的类
     def __init__(self,angle,velocity,height):#构造函数
        #根据给定的发射角度(angle),初始速度(velocity),初始高度(height)创建一个子弹对象(self)
        self.xpos=0.0#初始化x坐标为0.0
        self.ypos=height#初始化y坐标为输入的高度值
        theta=radians(angle)#将输入的角度值转换为弧度值
        self.xvel=velocity*cos(theta)#x的初始速度为输入的速度值在x轴上的投影
        self.yvel=velocity*sin(theta)#y的初始速度为输入的速度值在y轴上的投影
     def update(self,time):
        #更新子弹的状态
        self.xpos=self.xpos+time*self.xvel#在x方向上子弹匀速运动
        yvel1=self.yvel-9.8*time#即在y方向上有v=v0-gt
        self.ypos=self.ypos+time*(self.yvel+yvel)/2.0
        #在y方向上有y=y0+0.5*(v+v0)t=y0+v0t-0.5gt^2
        self.yvelf=yvel#将刚才计算出的v作为下次计算的v0
    def getY(self):
        #返回子弹的高度,即y坐标
        return self.ypos
    def getX(self):
        #返回子弹的飞出距离,即x坐标
        return self.xpos

bullet.py

#bullt.py   弹道计算程序   解决模块化问题的主程序-面向对象想的设计
from projectile.py import Projectile
def getInput():
    #输入计算所需的数值
    a=eval(raw_input("Enter the launch angle(in degrees):"))
    #输入发射角度(度)
    v=eval(raw_input("Enter the initial velocity(in meters/sec):"))
    #输入初始速度(米/秒)
    h=eval(raw_input("Enter the initial height(in meters):"))
    #输入初始高度(米)、
    t=eval(raw_input("Enter the time interval between position calcuations(in sec):"))
    #输入位置计算之间的时间间隔(秒)
    return a,v,h,t
def main():
    #主函数,用来组织调控各个模块
    angle,vel,h0,time=getInput()
    #将输入的各个参数赋给角度、速度、初始高度、时间等各个形参
    bullet=Projectile(angle,vel,h0)
    #调用Projectile类,并追踪子弹的飞行轨迹
    while bullet.getY()>=0:#y<0即子弹已经落在地面上才停止循环,否则一直循环追踪
        #>=是为了保证子弹即使从地面发射也能完成计算
        bullet.update(time)
        #通过Projectile中的update函数来更新子弹状态
    print "\nDistance traveled:{0:0.1f}meters.".format(bullet.getX())
    #以保留一位小数的浮点数类型(不足位则以0来补充)输出子弹此时X坐标
main()

面向对象程序设计的特点

  1. 封装:分开了是什么和怎么样工作两个问题,使对象的实际实现与使用是独立的;支持代码的复用
  2. 多态:使程序在不同情况下用同一个函数名字启用完全不同的方法
  3. 继承:可以建造系统中的类,避免重复性;新类经常是基于已存在的类,提升了代码的复用程度。

编程题

创建一个Set类表示集合,Set类需要包含以下方法:

  • Set(elements):创建一个Set对象(elements是初始列表)
  • addElement(x):将x加入到Set对象中
  • deleteElement(x):将x从集合中删去(如果集合中存在x);若不存在,则集合保持不变
  • member(x):根据x是否在集合中返回相应的True/False值
  • intersection(set2):返回一个新的Set对象,里面是此集合和set2元素的交集
  • union(set2):返回一个新的Set对象,里面是此集合和set2元素的并集
  • subtract(set2):返回一个新的Set对象,里面是此集合和set2元素的差集(不含set2 的元素)
    代码入下:
class Set:
    def __init__(Set,element):#构造函数
        Set.elements=element#初始化列表elements
    def addElements(Set,x):
        #将x加到Set对象中
        Set.elements.add(x)
        return Set.elements
   def member(Set,x):
        #判断x是否在集合中
        for i in Set.elements:
            if x==i:#若在集合中x的个数不是0,则返回True
                return True
            else:#否则返回False
                return False
   def deleteElement(Set,x):
        #将x从集合中删除(如果x存在的话)
        if Set.member(x)==True:#如果x存在的话,遍历elements,发现一个删除一个
            Set.elements.remove(x)
        return Set.elements
   def intersection(Set,set2):
        #返回Set与set2的交集
        set3=set({})#创建一个空集合
        set3=Set.elements.intersection(set2)#交集
   def union(Set,set2):
        #返回Set与set2的并集
        set3=set({})#创建一个空集合
        set3=set2.union(Set.elements)#并集
        return set3
   def subtract(Set,set2):
        #返回一个差集
        set3=set({})#创建一个空集合
        set3=Set.elements-set2#差集3
        return set3
 def Input():
    num=raw_input('Please enter the set: ')#连续输入(无空格)二位整数\两位字符(位数可修改)
    set1=set({})#建立一个空集合
    for i in range(len(num)/2):#输入了几个二位整数就循环几次
        set1.add(num[2*i]+num[2*i+1])#以每两位为一个整数存入set1
    return set1
 def main():
    set1=Input()#Set对象所包含的集合
    Sett=Set(set1)#将set1赋给Sett对象
    set2=Input()#集合set2
    x=raw_input('Enter the x:')#输入参数x
    print "\nAfter adding x, the collection elements are:\n",Sett.addElements(x)
    print "Is x in Collection Elements:\n",Sett.member(x)
    print "Delete x and set elements as:\n",Sett.deleteElement(x)
    print "The intersection of set elements and set 2 is:\n",Sett.intersection(set2)
    print "The union of set elements and set 2 is:\n",Sett.union(set2)
    print "The difference set between set elements and set 2 is:\n",Sett.subtract(set2)
if __name__=='__main__':
    main()