python核心阶段(五)—— 面向对象三大特性

1.封装

    概念:封装主要是指将一些属性和相关方法封装在一个对象中,对外隐藏内部具体实现细节

    作用:1)使用起来更加方便,类似于提供了一个工具箱

               2)保证数据的安全(设置私有属性)

               3)利于代码维护(代码维护时,直接在类内部修改即可,外部无需修改)

2.继承

 2.1 继承的基本知识

  • 概念:一个类"拥有"另外一个类的"资源"(指"非私有的"属性和方法使用权
  • 作用:资源重用                                                                                               
  • 分类:单继承(只继承了一个父类)、多继承(继承了多个父类)                                                     
  • 语法:

             class 子类名(父类名): 

                                       pass

                    父类名可以写多个,用逗号“,”隔开,越靠前继承的优先级越高        

  • 常用内置属性:__bases__                     查看类的所有父类构成元组                                                        
  • object 和 type 的区别:

        type:元类,是用来创建类的类

        object:类对象,主要是判别新式类(继承了object类)和经典类(没继承object类),

                      python3版本,在创建类时,默认继承object类,即:默认创建新式类

object 和 type 的区别

 2.2 继承下的影响 

    2.2.1 资源的继承

      在python中,继承是指对父类资源的使用权 /访问权

      除了私有的属性和私有的方法, 其他的基本都能继承(共有、受保护、内置)

      在子类中,不能修改父类的属性 / 方法,修改操作相当于在子类中新增一个同名属性

    2.2.2 资源的使用

  • 继承的几种形态以及遵循的准则
  • Python3.x之后新式类的方法解析顺序(MRO):C3算法
形态具体描述资源查找原则
单继承链一个子类只有一个父类

遵循"从下到上"的原则

自身 一> 父类 一> 父类的父类

无重叠的多继承链继承链无交叉, 无公共父类

遵循"单调"原则

 顺着一条链找到底

A 一> B 一> D 一> C 一> E

有重叠的多继承链继承链有交叉, 有公共父类

遵循"从下到上"的原则

一级一级查找

A 一> B 一> C 一> D

几种继承形态图示

  •  针对于几种标准原则的发展演变
 针对于几种标准原则的发展演变

  • 查看某个类的资源查找顺序的语法:
法一(inspect包)

import  inspect 

  inspect.getmro(类名)

法二(mro属性)

类名.__mro__

法三(mro函数)

类名.mro()

    2.2.3 资源的覆盖

      资源覆盖包括属性的覆盖和方法重写。在MRO的资源检索链中,若优先级高的类和优先级低的类都写了一个一样的资源(属性或方法),则在获取资源时,会优先选择优先级高的类中的资源,而摒弃优先级低的资源,就造成了“覆盖”的假象

       注意:如果子类方法调用了父类的方法,那么此时参数self和cls是调用这个方法的那个类/属性

    2.2.4 资源的累加 

       概念:在一个类的基础之上, 增加一些额外的资源

  • 场景一:子类相比于父类, 多一些自己特有的方法/属性

        实现方式:直接在子类中定义就可

  • 场景二:在被“覆盖”的方法基础之上,新增新的内容(即:保留旧的某个方法并扩展新内容)

        实现方式一:在高优先级类的方法中, 通过"类名"调用低优先级类的方法

                              这里不能用实例调用,会导致self输入不一致

                    弊端:对于有重叠的多继承链,会产生重复调用;代码不易维护

class B:
    def __init__(self):
        self.weight = 60
        self.height = 1.75

class A(B):  # A类继承了B类
    def __init__(self):
        B.__init__(self) # 通过类名调用B中的init,保留原来内容
                         # 这里不能通过其他方式调用,会导致self输入不一致
        self.bmi = 1  # 新增额外内容

a = A()
print(a.__dict__)

     

      实现方式二:在低优先级类的方法中, 通过"super"调用高优先级类的方法

              super是一个类,它只在新式类中有效,它主要起代理作用,帮助我们沿着MRO链条,找到下一个节点,去调用对应方法 

               语法:super(). 方法名           在 python3.x 的版本中,不需要填写参数,会自动补全

               实现原理:def super(cls参数一, inst参数二):
                                        mro = inst.__class__.mro()
                                        return mro[mro.index(cls) + 1]

                         相当于沿着参数二的mro顺序,找到参数一对应的节点+1,即参数一的下一个节点

# 继承关系  A 一> B,C 一> D
# 在这种情况下,如果使用方法一在B C中调用D,再在A中调用B C,就会重复调用D两次
# 使用super调用,就不会重复出现
class D(object):
    def __init__(self):
        print("d")

class B(D):
    def __init__(self):
        super().__init__()
        print("b")

class C(D):
    def __init__(self):
        super().__init__()
        print("c")

class A(B,C):
    def __init__(self):
        super().__init__()
        print("a")

A()

3.多态

  • 多态大致有两种含义:

            1)一个类, 所延伸的多种形态(animal可以延伸出dog cat...);

            2)调用时的多种形态(dog和cat中都有同一属性/方法,但调用时输出不同)

  • 多态在python中的体现:

          鸭子类型(动态类型的一种风格),它的关注点在于对象的"行为和属性"; 而非对象的"类型"

  •     回忆:

            python是强类型(类型强势,不会轻易自动修改)、动态类型(数据的类型在运行时可以判定,动态修改)

             而多态一般是体现在静态语言中,所以在python中没有真正意义上的多态,也不需要多态 

4.补充:抽象类、抽象方法

  • 概念

         抽象类 是指一个抽象出来的类,并不是某一个具化的类,它是一个不能直接创建实例的类,主要是用于被其他类继承

         抽象方法 是指抽象出来的一个方法,不具备具体实现,不能直接调用如果一个类中有抽象方法,当他被继承时,继承他的类中必须要具体定义这个方法

  • 例子:

           animal类就是一个抽象类,他只是存储了所有动物的一些特性,但并不能直接去使用,因为我们不知道到底是什么动物,同理animal的各种方法,如体型声音等也是如此

  • 在python中的实现:

          导入模块abc  ——> 设置类的元类为abc.ABCMeta  ——>  使用装饰器装饰抽象方法

                                                                                                        @abc.abstractmethod

5.案例 

  • 要求:

         1. 定义三个类, 小狗, 小猫, 人

         2.三个类具体要求如下:

            小狗: 姓名, 年龄(默认1岁);    吃饭, 玩, 睡觉, 看家(格式: 名字是xx, 年龄xx岁的小狗在xx)

            小猫: 姓名, 年龄(默认1岁);   吃饭, 玩, 睡觉, 捉老鼠(格式: 名字是xx, 年龄xx岁的小猫在xx)

            人:   姓名, 年龄(默认1岁), 宠物;  吃饭, 玩, 睡觉(格式: 名字是xx, 年龄xx岁的人在xx)
                    养宠物(让所有的宠物吃饭, 玩, 睡觉), 
                    宠物工作(让所有的宠物根据自己的职责开始工作) 

# 案例
# 我们发现在三个大类中,有很多相同的属性,所以我们可以先定义一个父类,让他们都继承即可

class Animal():
    def __init__(self, name, age=1):
        self.name = name
        self.age = age

    def eat(self):
        print(f"{self}吃饭")

    def play(self):
        print(f"{self}玩")

    def sleep(self):
        print(f"{self}睡觉")


class Person(Animal):   #定义人
    # 在创建小狗实例时,给它设置几个属性,所以这里应该定义实例属性

    def __init__(self,name,pet,age=1):
        super(Person,self).__init__(name,age)
        self.pet = pet

    def __str__(self):  # self本身的一个字符串描述  print(self)直接输出下面字符串
        return f"名字是{self.name}, 年龄{self.age}岁的人在"

    def yangPets(self):
        for pet in self.pet:
            pet.eat()
            pet.play()
            pet.sleep()

    def petWork(self):
        for pet in self.pet:
            pet.work()

class Dog(Animal):  #定义狗类
    # 在创建小狗实例时,给它设置几个属性,所以这里应该定义实例属性
    def __init__(self, name, age=1):
        super(Dog,self).__init__(name,age)

    def work(self):
        print(f"{self}看家")

    def __str__(self):  # self本身的一个字符串描述  print(self)直接输出下面字符串
        return f"名字是{self.name}, 年龄{self.age}岁的小狗在"


class Cat(Animal):  #定义猫类
    # 在创建小猫实例时,给它设置几个属性,所以这里应该定义实例属性
    def __init__(self, name, age=1):
        super(Cat,self).__init__(name,age)

    def work(self):
        print(f"{self}捉老鼠")

    def __str__(self):  # self本身的一个字符串描述  print(self)直接输出下面字符串
        return f"名字是{self.name}, 年龄{self.age}岁的小猫在"


d = Dog("卡布",5)
c = Cat("喵喵",3)
p = Person("李明",[d,c],25)

p.yangPets()
p.petWork()

6.总结:面向对象原则 SOLID(了解)

  • S:单一职责原则(一个类只负责一项职责)                                                                                      
  • O:开放封闭原则(对扩展开放,对修改关闭)                                                                                         
  •  L:里氏替换原则(使用父类引用的地方必须能使用子类对象)  
        
  •  I:接口分离原则(如果类包含了过多的接口方法,而这些方法在使用的过程中并非"不可分          割", 那么应当把他们进行分离)                                     

               所谓接口, 在Python中, 可以简单的理解为"抽象方法 

  •  D:依赖倒置原则(高层模块不应该直接依赖低层模,他们应该依赖抽象类或者接口块)

  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值