一、继承相关概念
1、语法:
2、定义:
3、优缺点:
4、相关概念:
5、相关内置函数:
6、继承内存图:
7、多继承:
二、多态相关概念
1、定义及作用:
2、重写概念:
3、运算符重载:
定义:让自定义的类生成的对象(实例)能够使用运算符进行操作。
三、基础技能代码:
代码1:
"""
继承语法 -- 方法
财产
皇位 #练习1:定义父类--宠物, 行为:吃
# 定义子类--狗, 行为:防守xx
# 定义子类--鸟, 行为:飞
#创建相应对象,调用相应方法.测试isinstance,issubclass函数
#14:35 """ # 学生 与 老师 在某种概念上是统一的
# 学生是 人
# 老师是 人
# class Person:
def say(self):
print("说") class Student(Person):
def study(self):
print("学习") class Teacher(Person):
def teach(self):
print("教") s01 = Student()
s01.study()
# 可以直接使用父类成员
s01.say() p02 = Person()
p02.say()
# 父类不能使用子类成员
# p02.study() t03 = Teacher()
t03.teach()
# 不能使用"兄弟"类成员
# t03.study() # 判断一个对象是否"兼容"一个类型
print(isinstance(s01,Person)) # True
print(isinstance(s01,Student)) # True
print(isinstance(s01,object)) # True print(isinstance(s01,Teacher)) # False
print(isinstance(p02,Student)) # False # 判断一个类是否"兼容"一个类型
print(issubclass(Student,Person)) # True
print(issubclass(Student,Teacher)) # False
print(issubclass(Student,(Teacher,Person))) # True
print(issubclass(Student,Student)) # True
代码2:
"""
继承语法 -- 数据
# 练习: 定义父类--宠物, 数据:名字
# 定义子类--狗, 数据:工作
# 创建相应对象,画出内存图
""" class Person:
def __init__(self,name):
self.name = name class Student(Person):
def __init__(self,name,score):
# 通过函数,调用父类方法
super().__init__(name)
self.score = score class Teacher(Person):
def __init__(self,name,salary):
super().__init__(name)
self.salary = salary s01 = Student("zs",100)
print(s01.score)
print(s01.name) p02 = Person("ww")
print(p02.name)
代码3:
"""
继承 -- 设计思想
面向对象设计原则
练习:exercise01.py
1. 开闭原则
开放 关闭
对扩展 对修改
允许增加新功能 不允许改变(增加/删除/修改)以前的代码 2. 依赖倒置(抽象)
使用抽象(父类),而不使用具体(子类).
"""
# 老张开车去东北
# 变化:飞机
# 火车
# 汽车
# ....... class Person:
def __init__(self, name):
self.name = name # def go_to(self, str_type, str_pos):
# if str_type == "汽车":
# Car().run(str_pos)
# elif str_type =="飞机":
# Airplane().fly(str_pos)
# # elif xxxxx: def go_to(self, vehicle, str_pos):
"""
写代码期间:
使用的是交通工具的,而不是汽车,飞机等
所以无需判断具体类型
运行期间:
传递具体的对象(汽车,飞机)
:param vehicle:
:param str_pos:
:return:
"""
# 如果传入的对象,不是交通工具,则退出.
if not isinstance(vehicle,Vehicle):
print("传入的不是交通工具")
return
vehicle.transport(str_pos) # class Car:
# def run(self, str_pos):
# print("行驶到", str_pos)
#
#
# class Airplane:
# def fly(self, str_pos):
# print("飞到", str_pos) class Vehicle:
"""
交通工具
"""
def transport(self, str_pos):
# 人为创造一个错误()
raise NotImplementedError()
# print("儿子们,必须有这个方法啊") class Car(Vehicle):
def transport(self, str_pos):
print("行驶到", str_pos) class Airplane(Vehicle):
def transport(self, str_pos):
print("飞到", str_pos) # ....
p01 = Person("老张")
# p01.go_to("汽车", "东北")
p01.go_to(Airplane(),"东北")
四、具体实例:
练习1:
# 练习:手雷爆炸了,可能伤害敌人,玩家.还有可能伤害未知事物(鸭子,树,房子).
# 要求:如果增加了新的事物,手雷代码不变. 17:15 class Grenade:
"""
手雷
""" def __init__(self, atk):
self.atk = atk def explode(self, *args):
"""
爆炸
:return:
"""
for item in args:
if not isinstance(item, Damageable):
print("类型不兼容")
return
item.damage(self.atk) class Damageable:
"""
可以受伤
""" def __init__(self, hp):
self.hp = hp def damage(self, value):
# 约束子类必须具有当前方法
# raise NotImplementedError()
self.hp -= value class Player(Damageable):
def damage(self, value=0):
# self.hp -= value
super().damage(value)
print("碎屏") class Enemy(Damageable):
def damage(self, value):
# self.hp -= value
super().damage(value)
print("播放动画") g01 = Grenade(10)
p02 = Player(100)
e03 = Enemy(50)
g01.explode(p02, e03)
练习2:
"""
有若干个图形(圆形,矩形........)
每种图形,都可以计算面积.
定义图形管理器,记录所有图形,提供计算总面积的方法.
要求:增加新的图形,不改变图形管理器代码.
""" class GraphicManager:
def __init__(self):
# 记录所有图形
self.__graphics = [] def add_graphic(self,g):
if not isinstance(g,Graphic):
return
self.__graphics.append(g) def get_total_area(self):
"""
计算总面积
:return:
"""
total_area = 0
for item in self.__graphics:
total_area += item.get_area()
return total_area class Graphic:
"""
图形
"""
def get_area(self):
pass class Circle(Graphic):
"""
圆形
"""
def __init__(self,radius):
self.radius = radius def get_area(self):
return self.radius ** 2 * 3.14 class Rectangle(Graphic):
"""
矩形
""" def __init__(self, length,width):
self.length = length
self.width = width def get_area(self):
return self.length * self.width manager = GraphicManager()
manager.add_graphic("ok")
manager.add_graphic(Rectangle(2,3))
manager.add_graphic(Circle(5))
# 加断点,调试
print(manager.get_total_area())
练习3:
# 1. 定义父类:武器,数据:攻击力,行为:购买(所有子类都一样).攻击(不知道怎么攻击)
# 定义子类:枪,数据:射速,行为:攻击
# 定义子类:手雷,数据:爆炸范围,行为:攻击
# 创建相应对象,调用相应方法.
# 画出内存图 class Weapon:
"""
武器
"""
def __init__(self,atk):
self.atk = atk def buy(self):
print("购买武器") def attack(self):
# 子类如果没有当前方法,就会报错
raise NotImplementedError() class Gun(Weapon):
"""
枪
"""
def __init__(self,atk,speed):
super().__init__(atk)
self.att_speed = speed def attack(self):
print("开枪啦") class Grenade(Weapon):
"""
手雷
""" def __init__(self, atk, range):
super().__init__(atk)
self.explode_range = range def attack(self):
print("爆炸啦") g01 = Gun(10,0.1)
g01.buy()
g01.attack() grenade01 = Grenade(50,10)
grenade01.buy()
grenade01.attack()
练习4:
# 2. 一家公司,有如下几种岗位:
# 普通员工:底薪
# 程序员:底薪 + 项目分红
# 销售员:底薪 + 销售额
# 定义员工管理器,记录所有员工,提供计算总薪资方法.
# 要求:增加新岗位,员工管理器代码不做修改.
# 体会:依赖倒置
class EmployeeManager:
"""
员工管理器
""" def __init__(self):
self.__all_employee = [] def add_employee(self, employee):
if not isinstance(employee, Employee):
return
self.__all_employee.append(employee) def get_total_salary(self):
"""
计算总薪资
:return:
"""
total_salary = 0
for item in self.__all_employee:
# 编码期间:item 认为是员工
# 运行期间:item 实际是具体员工
total_salary += item.get_salary()
return total_salary class Employee:
"""
员工类
作用:代表具体员工,隔离员工管理器与具体员工的变化.
""" def __init__(self, name, salary):
self.name = name
self.base_salary = salary def get_salary(self):
return self.base_salary class Programmer(Employee):
"""
程序员
""" def __init__(self, name, salary, bonus):
super().__init__(name, salary)
self.bonus = bonus def get_salary(self):
# return self.base_salary + self.bonus
# 扩展重写
return super().get_salary() + self.bonus class Salesmen(Employee):
"""
销售员
""" def __init__(self, name, salary, sale_value):
super().__init__(name, salary)
self.sale_value = sale_value def get_salary(self):
return super().get_salary() + self.sale_value * 0.05 manager = EmployeeManager()
manager.add_employee(Employee("zs",3000))
manager.add_employee(Programmer("xp",4000,10))
manager.add_employee(Programmer("xx",99999,6135138))
manager.add_employee(Salesmen("pp",3000,500)) re = manager.get_total_salary()
print(re) #练习:老王转岗
# 销售 --> 程序员
lw = Salesmen("老王",3000,500)
lw = Programmer("老王",8000,100000) # 重新创建新对象,替换引用.好比是开除"老王",招聘新"老王"
# 要求:对象部分改变,而不是全部改变.
练习5:
class Employee:
"""
员工类
""" def __init__(self, name,job):
self.name = name
# 成员变量的类型是岗位
self.job = job def calculate_salary(self):
"""
使用岗位,计算薪资.
:return:
"""
return self.job.get_salary() class Job:
"""
岗位
"""
def __init__(self,salary):
self.base_salary = salary def get_salary(self):
return self.base_salary class Programmer(Job):
"""
程序员
""" def __init__(self,salary, bonus):
super().__init__(salary)
self.bonus = bonus def get_salary(self):
# return self.base_salary + self.bonus
# 扩展重写
return super().get_salary() + self.bonus class Salesmen(Job):
"""
销售员
""" def __init__(self,salary, sale_value):
super().__init__(salary)
self.sale_value = sale_value def get_salary(self):
return super().get_salary() + self.sale_value * 0.05 #练习:老王转岗
# 销售 --> 程序员
# 继承关系
# lw = Salesmen("老王",3000,500)
# lw = Programmer("老王",8000,100000) # 重新创建新对象,替换引用.好比是开除"老王",招聘新"老王"
# 要求:对象部分改变,而不是全部改变. lw = Employee("老王",Salesmen(3000,500))
print(lw.calculate_salary())
# 转岗
lw.job = Programmer(8000,100000)
print(lw.calculate_salary())
练习6:
"""
内置可重写函数 """ class Wife:
def __init__(self,name,age):
self.name = name
self.age = age def __str__(self):
# 返回给人看
return "奴家叫:%s,年芳:%d"%(self.name,self.age)
def __repr__(self):
# 返回给解释器看
return 'Wife("%s",%d)'%(self.name,self.age) w01 = Wife("金莲",25)
print(w01)# 将对象转换为字符串
# re = eval("1 + 5")
# print(re)
# w02 = eval('Wife("金莲",25)')
# w03 = eval(input(""))
#创建了新对象
w02 = eval(w01.__repr__())
print(w02)
w01.name ="莲莲"
print(w02.name)
练习7:
# 练习: 重写 StudentModel 类 __str__ 方法 与__repr__方法
# 创建学生对象,创建学生对象列表.分别print class StudentModel:
def __init__(self, name="", age=0, score=0, id=0):
self.id = id
self.name = name
self.age = age
self.score = score def __str__(self):
return "我的编号是:%d,姓名是:%s,年龄是:%d,成绩是:%d."%(self.id,self.name,self.age,self.score) def __repr__(self):
return 'StudentModel("%s",%d,%d)'%(self.name,self.age,self.score) s01 = StudentModel("zs",24,100)
s02 = eval(s01.__repr__())
print(s02)
print(s01)
list01 = [s01,s02]
print(list01)
练习8:
"""
运算符重载
""" # print("a" + "b")
class Vector:
"""
向量
"""
def __init__(self, x):
self.x = x def __str__(self):
return "向量的x变量是:%s"%self.x # 对象 +
def __add__(self, other):
return Vector(self.x + other) # + 对象
def __radd__(self, other):
return Vector(self.x + other) # 累加:在原有对象基础上进行操作,不创建新对象.
def __iadd__(self, other):
self.x += other
return self def __lt__(self, other):
return self.x < other v01 = Vector(10)
v02 = v01 + 5
# print(v02)
# 练习:实现向量类 与 整数 做 减法/乘法运算 17:25
v03 = 5 + v01
# print(v03)
v04 = v01 + v02
# print(v04)
# 练习:实现整数 与 向量 做 减法/乘法运算
# 向量 向量 list01 = [1]
list02 = list01 + [2]
print(list01)
list01 += [2]
print(list01) print(id(v01))
# 累加含义:在原有对象基础上,增加新值
v01 += 1
print(v01)
print(id(v01))
# 练习:实现向量类 与 整数 做 累计减法/累计乘法运算 print(v01 < 2)