Python基础之面向对象3(继承)

一、继承相关概念

  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)

 

posted @ 2019-04-17 18:56  一如年少模样  阅读(608)  评论(0编辑  收藏  举报