Python学习笔记-面向对象的程序设计
面向过程的程序设计的步骤:
- 清楚地分析程序从输入到输出的各个步骤
- 按照程序执行过程从前到后编写各个步骤,采用调用的方式将各步骤组织起来
- 在编写过程中,将高耦合部分封装成模块或函数,尽量实现模块化设计
- 输入参数,按照程序执行过程开展调试
基本思想:将任务分解成特定的功能模块,再将功能模块按照运行步骤组织起来。
主要用于一般程序,不适用于大型软件的开发。
面向对象的程序设计
对象的两种特征:状态和行为
基本步骤:
- 根据功能,抽象出业务对象。
- 对需求进行合理分层,构建相对独立的业务模块,设计业务逻辑,并围绕对象利用封装、继承、多态等基本设计方法,抽象业务需求。
- 在编写过程中,利用对象之间的关系组织功能需求。
- 以对象为单位输入参数、开展测试。
对类和对象的抽象:即通过功能划分将业务逻辑分解成相对独立的功能体,将业务逻辑组织为对象间的关系。
寻找最高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。
两个问题:
- 子弹所处的高度,通过高度可以计算子弹什么时候落地
- 距离,用于跟踪子弹能飞多远
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()
面向对象程序设计的特点
- 封装:分开了是什么和怎么样工作两个问题,使对象的实际实现与使用是独立的;支持代码的复用
- 多态:使程序在不同情况下用同一个函数名字启用完全不同的方法
- 继承:可以建造系统中的类,避免重复性;新类经常是基于已存在的类,提升了代码的复用程度。
编程题
创建一个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()