python多态与继承

    科技2022-07-13  132

    python多态与继承

    一、继承1、概念2、单继承1)单父类与子类的继承2)子类、父类、爷爷类的关系3)方法的重写(1)方法重写:覆盖(2)方法重写:拓展——super()方法 4)父类的私有属性与私有方法 3、多继承父类有相同的方法名时 二、多态案例 三、类属性和类方法1、实例2、类对象3、类属性4、类方法5、静态方法 四、案例1、需求 面向对象三大特性:

    封装:根据职责将属性和方法封装到一个抽象的类中继承:实现代码的重用,相同代码不需要重复的编写多态:不同的对象调用相同的方法,产生不同的结果,增加代码的灵活度

    一、继承

    1、概念

    继承的概念: 1、子类拥有父类的所有方法和属性 2、不包括私有属性和私有方法 继承的优点: 1、实现代码重用 2、简化代码的结构 3、便于代码的维护和管理 4、但是不能够提升代码的运行速度

    每个对象都有相同的方法,代码大量重复。

    2、单继承

    1)单父类与子类的继承

    class 类名(父类名): pass

    子类继承父类,可以直接享受父类中已经封装好的方法,不需要再次开发;子类中应该根据职责封装子类特有的属性和方法。

    class Animal: def __init__(self): self.name = "动物" self.age = 2 def eat(self): print("%s 都爱吃" % self.name) # 单继承 class Cat(Animal): def catch(self): print("猫抓老鼠") animal = Animal() print(animal.name) print(animal.age) animal.eat() # 父类对象不能调用子类的方法,也不能访问子类的属性 print("*" * 50) # 子类对象调用父类的方法和属性 cat = Cat() print(cat.name) print(cat.age) cat.eat() cat.catch()

    2)子类、父类、爷爷类的关系

    class Animal: def __init__(self): self.name = "动物" self.age = 2 def eat(self): print("%s 都爱吃" % self.name) # 单继承 class Cat(Animal): def catch(self): print("猫抓老鼠") class Bosicat(Cat): def sing(self): print("波斯猫会唱歌") animal = Animal() print(animal.name) print(animal.age) animal.eat() print("*" * 50) # 子类对象调用父类的方法和属性 cat = Cat() print(cat.name) print(cat.age) cat.eat() cat.catch() print("*" * 50) # 子类对象调用父类以及爷爷类的方法和属性 bsm = Bosicat() print(bsm.name) print(bsm.age) bsm.eat() bsm.catch() bsm.sing()

    3)方法的重写

    重写的概念: 子类中有与父类相同的方法名, 重写的原因: 当父类的函数无法满足子类的需求,则需要方法的重写 前提: 两者要有继承的关系 重写的两种方式: 1、覆盖父类的方法:子类重写的方法与父类完全不同 2、对父类方法进行拓展:子类重写的方法是在父类方法的基础上进行功能拓展

    (1)方法重写:覆盖

    class Animal: def __init__(self): self.name = "动物" self.age = 2 def eat(self): print("%s 都爱吃" % self.name) # 单继承 class Cat(Animal): def catch(self): print("猫抓老鼠") class Bosicat(Cat): # 重写父类的功能 def catch(self): print("波斯猫抓鱼") def sing(self): print("波斯猫会唱歌") bsm = Bosicat() bsm.catch()

    (2)方法重写:拓展——super()方法

    class Animal: def __init__(self): self.name = "动物" self.age = 2 def eat(self): print("%s 都爱吃" % self.name) # 单继承 class Cat(Animal): def catch(self): print("猫抓老鼠") class Bosicat(Cat): # 对父类方法实现功能拓展 def catch(self): # ①super().重写的方法名 # super()在子类中调用父类重写的方法 super().catch() # 在父类的方法上进行了拓展 # ② 父类名.方法名(self) # 此方法不推荐,因为父类名修改后,在调用的地方也需要修改 print("波斯猫抓鱼") bsm = Bosicat() bsm.catch()

    4)父类的私有属性与私有方法

    class Father: """父类""" def __init__(self): # 共有属性 self.name = "老林" # 私有属性,带有前置双下划线的属性 self.__pwd = 111111 def eat(self): """吃方法""" print("%s 爱吃东西,使用密码 %d 来买东西" % (self.name,self.__pwd)) # 私有方法,前置双下划线的方法 def __secret(self): """私有方法""" print("%s 的卡密码是%d" % (self.name,self.__pwd)) class Son(Father): """子类""" def run(self): print("小林跑") lin = Son() print(lin.name) # 在类外无法访问私有属性,在类内可以访问 lin.eat() print(dir(lin))

    给父类设置接口,用来调用父类的私有属性和私有方法

    class Father: """父类""" def __init__(self): # 共有属性 self.name = "老林" # 私有属性,带有前置双下划线的属性 self.__pwd = 111111 def eat(self): """吃方法""" print("%s 爱吃东西,使用密码 %d 来买东西" % (self.name,self.__pwd)) # 私有方法,前置双下划线的方法 def __secret(self): """私有方法""" print("%s 的卡密码是%d" % (self.name,self.__pwd)) # 在类的内部提供对外访问私有属性的接口 def get_pwd(self): """获取私有属性""" return self.__pwd def set_pwd(self,new_pwd): """设置私有属性""" self.__pwd = new_pwd def func_secret(self): """调用私有方法""" self.__secret() class Son(Father): """子类""" def run(self): print("小林跑") lin = Son() print(lin.name) # 在类外无法访问私有属性,在类内可以访问 lin.eat() print(lin.get_pwd()) lin.set_pwd(123456) print(lin.get_pwd()) lin.func_secret()

    3、多继承

    多继承的概念: 子类可以拥有多个父类,并具有所有父类的属性和方法

    class Ma: """马类""" def __init__(self): self.name = "马" def run(self): print("马跑得快") class Lv: """驴类""" def walk(self): print("驴走得远") class Luozi(Ma,Lv): """骡子类""" pass luo = Luozi() print(luo.name) luo.run() luo.walk()

    父类有相同的方法名时

    其中object类时python为所有对象提供的基类,提供有一些内置的属性和方法

    class Ma: """马类""" def run(self): print("马跑得快") def walk(self): print("马走不远") class Lv: """驴类""" def walk(self): print("驴走得远") def run(self): print("驴跑不快") class Luozi(Ma,Lv): """骡子类""" pass luo = Luozi() luo.run() luo.walk() # 方法解析顺序 print(Luozi.__mro__)

    二、多态

    多态是不同的对象调用相同的方法,产生不同的结果状态

    多态可以增加代码的灵活度 以继承和重写父类方法为前提 是调用方法的技巧,不会影响到类的内部设计

    案例

    class Dog: """普通狗类""" def __init__(self,name): self.name = name def game(self): print("%s在地上玩耍" % self.name) class XiaoTianQuan(Dog): """哮天犬类""" def __init__(self,name): self.name = name def game(self): print("%s 在天上玩耍" % self.name) class Person: """人类""" def __init__(self, name): self.name = name def play_with_dog(self,dog): """和狗玩的方法""" print("人 %s 和狗 %s 一起玩" % (self.name,dog.name)) dog.game() peanut = Dog("花生") xtq = XiaoTianQuan("哮天犬") lin = Person("林") lin.play_with_dog(peanut) print("*"*50) lin.play_with_dog(xtq)

    三、类属性和类方法

    1、实例

    1、创建出来的,具有内存空间的对象就是实例对象 2、创建对象的动作叫做实例化 3、对象的属性叫做实例属性 4、对象调用的方法叫做实例方法

    2、类对象

    3、类属性

    # 需求:统计当前类模板创建了几个实例对象? class Person(object): """人类""" # 类属性,定义在方法的外边,类的内部 # 作用:主要用来记录类对象的相关特征 # 类属性 count = 0 print("类模板初始化一次") def __init__(self, name): self.name = name print("初始化方法__init__") # 使用类属性统计当前类模板创建了几个实例对象 # 访问类属性需要通过类名来访问 类名.类属性 Person.count += 1 def eat(self): print("%s 爱吃美食" % self.name) lin = Person("lin") lin1 = Person("lin1") lin2 = Person("lin2") # 类外访问类属性的方式 # 1、类名.类属性名 print(Person.count) # 2、实例对象.类属性名 print(lin.count) # 修改类属性 # 类名.类属性 = 值 # 修改类属性不可用实例对象.类属性名的方式,因为该方式仅仅是给对象加实例属性 Person.count = 10 print(Person.count)

    4、类方法

    类方法是针对类对象的方法。

    class Person(object): """人类""" # 类属性 count = 0 def __init__(self, name): self.name = name def eat(self): print("%s 爱吃美食" % self.name) # classmethod是装饰器,也叫修饰器,告诉python解释器这是一个类方法 @classmethod def get_count(cls): """类方法""" print("1、类方法用于处理类属性或调用其他类方法") print("2、cls参数保存的是当前类对象的引用",cls) cls.count += 100 return cls.count print(Person) # 调用类方法 # 类对象名.类方法名 print(Person.get_count())

    5、静态方法

    class Person(object): """人类""" # 类属性 count = 0 def __init__(self, name): self.name = name def eat(self): print("%s 爱吃美食" % self.name) # classmethod是装饰器,也叫修饰器,告诉python解释器这是一个类方法 @classmethod def get_count(cls): """类方法""" print("1、类方法用于处理类属性或调用其他类方法") print("2、cls参数保存的是当前类对象的引用", cls) cls.count += 100 return cls.count # staticmethod是装饰器 @staticmethod def func_static(): """静态方法""" print("1、静态方法不需要self也不需要cls参数") print("2、静态方法中不需要实例属性也不需要类属性") print("3、静态方法中不需要实例方法也不需要类方法") print("3、静态方法中不需要实例方法也不需要类方法") print("4、静态方法不能破坏类的封装性") # 调用静态方法 # 1、类名.静态方法名 Person.func_static() # 2、实例名.静态方法名

    四、案例

    1、需求

    class Game: """游戏类""" # 类属性 top_score = 0 def __init__(self,player_name): self.player_name = player_name # 静态方法显示游戏帮助信息 @staticmethod def show_help(): print("帮助信息") # 类方法显示历史最高分 @classmethod def show_top_score(cls): print("历史最高分为:",cls.top_score) def start_game(self): print("游戏开始") print("%s 玩家正在游戏" % self.player_name) # 修改历史最高分 Game.top_score += 100 Game.show_help() Game.show_top_score() gamer = Game("lin") gamer.start_game() Game.show_top_score()

    Processed: 0.012, SQL: 8