课程:Python面向对象
进度:day1
主要内容:
1. 面向对象的概念
2. 面向对象的三大特性:封装、继承、多态
3. 面向对象的技术特性
4. 方法重载、运算符重载
5. 面向对象的设计
今天内容提要
1. OOP概念:以对象为中心,关注功能、关注结果
1)类和对象(重点)
2)如何定义类(重点)
3)类的构成(重点)
4)封装(重点)
5)继承(重点)
今天内容
1. 面向对象基本概念
1)面向过程:考虑实现过程、考虑每一步如何做
代码组织单位:函数
2)面向对象
a)提出的原因
- 成本和可行性
- 代码复用,提高开发效率
- 软件既要保持稳定性,又要满足不断变更
对扩展开放,对修改封闭
- 面向过程方式,在某些领域有局限性
b) 什么是面向对象
- Object Orainted Programming(简写OOP)
关注对象,把事物看做一个一个对象,以对象为中心
把事物归纳成一个一个的类
- 提供了另一种分析、解决问题的方式
c) 优点
- 思想方法层面:更有利于归纳、分析、解决问题
更接近于人的思维方式
- 技术层面
重用性:有利于代码复用,提高开发效率
扩展性:能够方便对现有代码进行扩展和改写
灵活性:程序设计具有更多的灵活性、弹性
- 适用场景
面向过程:系统级软件,嵌入式
面向对象:企业级应用,图形库,游戏
- 类和对象 (重点)
类(class):具有共同特征事物的统称。例如学生,汽车
对象(object): 类当中一个特殊的个体,特定、具体的
- 类的构成 (重点)
属性:描述对象“有什么”,数据特征
行为:描述对象“能干什么”,行为特征
- Python中类的定义 (重点)
class ClassName([父类列表]):
"类的代码"
# 属性(一般通过__init__构造方法创建)
# 方法1
# 方法2
# ......
说明: class 定义类的关键字
ClassName 类名称(一般以大写字符开头)
父类列表 发生继承时候,表示从哪个类继承
1 # ellipse.py 2 # 面向过程、面向对象编程比较 3 # 计算椭圆周长、面积 4 5 # 面向过程方式 6 a = 2.0 # 短半径 7 b = 3.0 # 长半径 8 len = 2 * 3.14 * a + 4 * (b - a) 9 print("a=%f, b=%f, len=%f" % (a,b,len)) 10 11 area = 3.14 * a * b 12 print("a=%f, b=%f, area=%f" % (a,b,area)) 13 14 # 面向对象方式 15 class Ellipse: # 定义椭圆类 16 #类中的函数, 称之为方法 17 def __init__(self, a, b): # 构造方法 18 self.a = a # 属性:短半径 19 self.b = b # 属性:长半径 20 # 2 * pi * 短半径 + 4(长半径 - 短半径) 21 def calc_len(self): #计算周长 22 return 2 * 3.14 * self.a + 23 4 * (self.b - self.a) 24 25 def calc_area(self): #计算面积 26 return 3.14 * self.a * self.b 27 28 e = Ellipse(2.0, 3.0) # 实例化:创建椭圆对象 29 len = e.calc_len() # 获得椭圆周长 30 area = e.calc_area() # 获得椭圆面积 31 print("a=%f,b=%f, len=%f, area=%f" % 32 (e.a, e.b, len, area)) 33 34 35 36
- 示例:定义一个汽车类(AutoMobile)
代码见auto_mobile.py
1 # auto_mobile.py 2 # 汽车类 3 import random 4 class AutoMobile: 5 # 构造方法,主要作用是对属性进行初始化 6 def __init__(self, name, 7 color, output_volumn): 8 self.name = name # 名称 9 self.color = color # 颜色 10 self.output_volumn = output_volumn#排量 11 self.__distance = 0.00 # 私有属性 12 self.__fuel_cons = 8.0 # 每百公里耗油量 13 14 def __calc_distance(self): # 计算行驶里程方法 15 dist = random.randint(1,400) 16 self.__distance += dist # 改变行驶里程 17 18 def get_distance(self): # 获得行驶里程 19 return self.__distance # 返回行驶里程属性 20 21 def startup(self): # 启动方法 22 print("汽车启动") 23 24 def run(self): # 行驶方法 25 self.__calc_distance() # 调用行驶里程计算方法 26 real_fuel_con = self.__fuel_cons / 100 27 * self.__distance 28 print("汽车行驶了%.2f公里,油耗%.2f升" % 29 (self.__distance, real_fuel_con)) 30 31 def stop(self): # 停止方法 32 print("汽车停止") 33 34 def info(self): # 打印汽车信息 35 print("名称:%s,颜色:%s,排量:%.2f" 36 %(self.name, self.color, 37 self.output_volumn)) 38 39 if __name__ == "__main__": 40 # 实例化:根据类创建对象(根据模型制作具体产品) 41 am = AutoMobile("家用轿车", "红色", 2.0) 42 am.startup() # 启动汽车(调用汽车方法) 43 am.run() # 行驶 44 am.stop() # 停止 45 am.info() # 查看汽车对象信息 46 # 通过调用get_distance()获取行驶里程 47 print("行驶里程:%.2f" % am.get_distance()) 48 49 50
1 # car.py 2 # 家用小汽车类,继承示例 3 from auto_mobile import * 4 5 # 定义Car类,继承自AutoMobile类 6 class Car(AutoMobile): 7 pass 8 9 if __name__ == "__main__": 10 mycar = Car("小汽车", "蓝色", 1.40) 11 mycar.startup() #启动 12 mycar.run() #行驶 13 mycar.stop() #停止 14 mycar.info() #打印信息 15
- OOP小结:
- 使用class AutoMobile定义了一个类,类中包含了
名称、颜色、排量等属性;启动(startup), 行驶(run),
停止(stop),打印信息(info)等方法
- 方法在类的内部定义,也叫成员函数或方法,定义了
类“能干什么”,或“具有哪些功能”。和普通函数
有个重要差别,就是必须以self作为第一个参数。self
自动绑定调用该方法的对象
- 实例化:创建一个类的对象
am = AutoMobile("家用轿车", "红色", 2.0)
* 该语句执行成功后,会返回一个对象,通过赋值语句
将该对象绑定到am变量上
* 实例化对象时,要传入的参数根据__init__方法确定
- __init__()方法,称之为“构造方法”
在对象被创建时自动调用
作用是创建属性,并且进行初始化
- 对象被创建后,可以通过"对象.方法名()"来调用方法
通过"对象.属性"来访问对象的属性
2. 面向对象三大特征: 封装、继承、多态
1)封装
- 将属性、方法放到类的内部
- 对象对外提供了一组方法(接口),来对类的数据进行
访问
- 对于一个类或对象,外部主要关注功能,而不是功能的实现
面向对象编写程序三步曲(记住,理解,应用)
第一步:设计编写类。根据业务逻辑,从具体事物中归纳、
抽象出共同的属性、方法,并编写代码
class 类名:
#构造方法
#其它方法
第二步:根据定义的类,实例化一个对象
ak = AK47()
awp = AWP()
第三步:调用对象方法,使用类所提供的功能
ak.reload()
ak.fire()
awp.reload()
awp.fire()
2)继承
a)代码冗余:不同模块中相同或相似的代码
导致的问题
- 重复劳动
- 编码、测试工作量增大
- 修改、维护困难
b)继承
- 将事物共同的特征抽象出来,定义到父类中
子类继承父类,自动获得父类的行为和属性
- 继承描述事物的共同特征
- 继承能够减少代码冗余,减少工作量,提升效率
使得代码更容易维护
c)几个相关概念
- 父类(基类,超类)、子类(派生类)
- 父类相对子类更抽象、范围更宽泛
子类相对于父类更具体、范围更狭小
- 单继承(只有一个父类,Java)
多继承(超过一个父类, Python/C++)
d)Python如何实现继承
class 类名称(父类1[, 父类2...]):
类的实现代码
e) 通过继承改写AK47,AWP类,添加父类Gun
见改写后的ak47.py, awp.py, gun.py, test.py
1 # ak47.py 2 # AK47类 3 from gun import * 4 5 class AK47(Gun): #继承自Gun类 6 pass
1 # awp.py 2 # 狙击枪类 3 from gun import * 4 5 class AWP(Gun): #AWP类,继承自Gun类 6 def openTelescope(self): #打开瞄准镜 7 print("瞄准镜已打开") 8 9 def closeTelescope(self): #关闭瞄准镜 10 print("瞄准镜已关闭") 11
1 # gun.py 2 # 枪械类 3 class Gun: 4 def __init__(self, name, max_bullets, 5 bullet_left,dest_ratio, 6 firing_bullets): 7 self.name = name #名称 8 self.max_bullets = max_bullets#弹夹容量 9 self.bullet_left = bullet_left#剩余子弹 10 self.dest_ratio = dest_ratio #杀伤系数 11 # 每次开火击发子弹数量 12 self.firing_bullets = firing_bullets 13 14 def reload(self): # 填弹 15 self.bullet_left = self.max_bullets 16 print("填弹完成,剩余子弹%d发" % 17 self.bullet_left) 18 19 def fire(self): # 开火 20 if self.bullet_left <= 0:#没子弹 21 print("请填弹") 22 return 23 24 if self.bullet_left >= self.firing_bullets: 25 self.bullet_left -= self.firing_bullets 26 else: #剩余子弹小于一次击发打出的子弹 27 self.bullet_left = 0 #全部打出 28 29 # 计算杀伤力 30 damage = int(self.dest_ratio*100) 31 32 # 打印,模拟开火 33 print("%s开火,杀伤力%d,剩余子弹%d" % 34 (self.name, damage, self.bullet_left)) 35
1 # test.py 2 # 测试程序 3 import ak47 4 import awp 5 6 ak = ak47.AK47("AK47", 30, 0, 0.4, 3) #实例化AK47对象 7 ak.reload() #填弹 8 ak.fire() #开火 9 ak.fire() 10 print("----------------") 11 awp = awp.AWP("AWP", 10, 0, 1.0, 1) #实例化AWP对象 12 awp.reload() 13 awp.fire() 14 15 ak2 = ak47.AK47("AK47", 20, 0, 0.4, 3)
f)继承小结
- 通过归纳、抽象,将共同特征(属性,行为)放到父类中
子类通过继承,获得父类的行为和属性
- 能够消除代码冗余
- 能够在不改变父类代码的情况下,子类添加特有的行为
和属性(例如AWP类中的openTelescope和
closeTelescope方法),从而实现功能扩展、变更
作业:
1)定义一个鸟类(Bird),具有吃(eat),飞行(fly),
繁殖(reproduction)方法
2)定义老鹰类(Eagle),鸵鸟类(Ostrich)类,
继承自Bird类
3)编写测试代码,测试eat,fly,reproduction方法
1 # bird.py 2 # 鸟类 3 class Bird: 4 def __init__(self, name): 5 self.name = name 6 7 def eat(self): # 吃方法 8 print("%s正在吃饭" % self.name) 9 10 def fly(self): # 飞行 11 print("%s正在飞行" % self.name) 12 13 def reproduction(self): # 繁殖 14 print("%s是卵生" % self.name) 15 16 class Eagle(Bird): # 老鹰类,继承自Bird 17 def eat(self): # 重写eat方法 18 print("我是%s,我喜欢吃肉" % self.name) 19 20 def fly(self): 21 print("我是%s,飞的又高又快" % self.name) 22 23 class Ostrich(Bird): # 鸵鸟类,继承自Bird 24 def fly(self): # 重写fly方法 25 print("我是%s,太重了不能飞" % self.name) 26 27 def eat(self): 28 print("我是%s,我是杂事动物" % self.name) 29 30 if __name__ == "__main__": 31 eagle = Eagle("老鹰") 32 eagle.eat() 33 eagle.fly() 34 eagle.reproduction() 35 print("") 36 ostrich = Ostrich("鸵鸟") 37 ostrich.eat() 38 ostrich.fly() 39 ostrich.reproduction() 40