面向对象(进阶)

  • 目录

    私有属性和方法

    单继承

    方法的重写

    多继承

    多态

    类属性

    类方法和静态方法

    方法综合

    单例设计模式


  • 私有属性和方法

    • 在实际开发中,对象 的 某些属性或方法 可能只希望在类的内部被使用,而 不希望在外部被访问到
    • 私有属性 就是 对象不希望公开的 属性
    • 私有方法 就是 对象不希望公开的 方法
    • 定义方式
    • 在 定义属性或方法时,在属性名或者方法名前 增加两个下划线,定义的就是私有 属性或方法
    • 私有属性和方法在外界不能直接被访问
    • 伪 私有属性和私有方法
    • Python中没有真正意义上的私有
    • 在给 属性、方法 命名时,实际是对名称做了一些特殊处理,使得外界无法访问
    • 处理方式:在 名称前面加上 _类名 _类名__名称
    • 提示:在日常开发中,不要使用这种方式,访问对象的 私有属性 或 私有方法
    • 面向对象的三大特征
    • 1.封装 根据 职责 将 属性 和 方法 封装 到一个抽象的类 中
    • 2.继承 实现代码的重用,相同的代码不需要重复的编写
    • 3.多态不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度
  • 单继承

    • 继承的概念:子类拥有 父类的所有 方法和 属性
    • 继承的语法:
    • 子类 继承自 父类,可以直接享受父类中已经封装好的方法,不需要再次开发
    • 子类中应该根据 职责,封装子类特有的 属性 和方法

    • 继承的传递性
    • C 类从B 类继承,B类又从A 类继承
    • 那么 C类就具有 B 类和A 类的所有属性和方法
    • 子类 拥有 父类 以及 父类的父类 中封装的所有 属性 和 方法

    • 返回值

  • 方法的重写

    • 子类拥有 父类的所有 方法和 属性
    • 子类 继承自 父类,可以直接享受父类中已经封装好的方法,不需要再次开发
    • 当 父类 的方法实现不能满足子类需求时,可以对方法进行重写(override)
    • 重写 父类方法有两种情况
    • 1、覆盖父类的方法
    • 对父类方法进行扩展
    • 覆盖父类的方法
    • 如果在开发中,父类的方法实现和子类的方法实现完全不同
    • 就可以使用覆盖的方式,在子类中 重新编写 父类的方法实现
    • 具体的实现方式,就相当于在 子类中 定义了一个 和父类相同名的方法并且实现
    • 重写之后,在运行时,只会调用 子类中重写的方法,而不再会调用父类封装的方法
    • 对父类方法进行拓展
      • 如果在开发中,子类的方法实现 中 包含 父类的方法实现
        • 父类原本封装的方法实现 是 子类方法的一部分
      • 就可以使用扩展的方式
        • 在子类中 重写 父类的方法
        • 在需要的位置使用**super( ).**父类方法来调用父类方法的执行
        • 代码其他的位置针对子类的需求,编写子类特有的代码实现
      • 关于 super
        • 在 python中 super是一个 特殊的类
        • super()就是使用 super类创建出来的对象
      • 最常使用的场景就是在 重写父类的方法时,调用在父类中封装的方法实现
    • 调用父类方法的另外一种方式(知道)
    • 在 python 2.x时,如果需要调用父类的方法,还可以使用以下方式
    • 父类名.方法(self)
    • 这种方式,目前在python 3.x 还支持这种方式
    • 这种方法不推荐使用,因为一旦 父类发生变化,方法调用位置的类名同样需要修改
  • 多继承

    • 子类可以拥有 多个父类,并且具有所有父类 的属性和 方法
    • 例如: 孩子 会继承自己父亲 和 母亲 的 特性

    • 语法

    • 多继承的使用注意事项
    • 如果 不同的父类 中存在 同名的方法,子类对象 在调用方法时,会调用哪个父类中的方法呢?
    • 提示: 开发时,应该尽量避免这种容易产生混淆的情况!——如果 父类之间 存在 同名的属性或者方法,应该 尽量避免 使用多继承

    • Python 中的 MRO——方法搜索顺序
    • Python中针对 类 提供了一个 内置属性__mro__可以查看 方法搜索顺序
    • MRO 是method resolution order, 主要用于在多继承时判断 方法、属性 的 调用路径
    • 在搜索方法时,是按照__mro__的输出结果 从左至右 **的顺序查找的
    • 如果在当前类中找到方法,就直接执行,不再搜索
    • 如果没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索
    • 如果找到最后一个类,还没有找到方法,程序报错
    • 新式类和旧式类
    • object是 Python为所有对象提供的 基类,提供有一些内置的属性和方法,可以使用dir 函数查看
    • 新式类:以 object 为基类的类,推荐使用
    • 经典类: 不以 object为基类的类,不推荐使用
    • 在 Python 3.x 中定义类时,如果没有指定父类,会 默认使用 object 作为该类的基类——python3.x 中定义的类都是 新式类
    • 在 Python 2.x 中定义类时,如果没有指定父类,则不会以object 作为基类
    • 新式类 和 经典类 在多继承时——会影响到方法的搜索顺序
    • 为了保证编写的代码能够在Python 2.x 和Python 3.x 运行
    • 今后在定义类时,如果没有父类,建议统一继承自object
  • 多态

    • 1、封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中
      • 定义类的准则
      • 2、继承 实现代码的重用,相同的代码不需要重复的编写
      • 设计类的技巧
      • 子类针对自己特有的需求,编写特定的代码
      • 3、多态 不同的 子类对象,调用相同的父类方法,产生不同的执行结果
      • 多态 可以 增加代码的灵活度
      • 以 继承 和 重写父类方法 为前提
      • 是调用方法的技巧,不会影响到类的内部设计

    • 返回值

  • 类属性

    • 类的结构
    • 使用面向对象开发,第 1 步是设计 类
    • 使用 类名( ) 创建对象, 创建对象 的动作有两步:
    • 在内存中为对象分配空间
    • 调用初始化方法__init__为 对象初始化
    • 创建对象后,内存中就有了一个对象的 实实在在 的存在— 实例

    • 因此,通常也会把:
    • 1.创建出来的对象 叫做 类 的 实例
    • 2.创建对象的动作叫做 实例化
    • 3.对象的属性 叫做 实例属性(在init中封装的属性)
    • 4.对象调用的方法 叫做 实例方法
    • 在程序执行时
    • 对象各自拥有自己的实例属性
    • 调用对象方法,可以通过self
    • 访问自己的属性
    • 调用自己的方法
    • 结论
    • 每一个对象,都有自己独立的内存空间,保存各自不同的属性
    • 多个对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用,传递到方法内部
    • 类是一个特殊的对象
    • Python 中 一切皆对象:
    • class AAA: 定义的类属于 类对象
    • obj1 = AAA( ) 属于 实例对象
    • 在程序运行时,类 同样 会被加载到内存
    • 在 python中,类 是一个特殊的对象 ——类对象
    • 在程序运行时,类对象 在内存中 只有一份,使用 一个类可以创建出 很多个对象实例
    • 除了封装 实例 的 属性 和 方法 外,类对象 可以拥有自己的属性和 方法
    • 1.类属性
    • 2.类方法
    • 通过 类名. 的方式可以 访问类的属性
    • 或者 调用类的方法

    • 类属性和实例属性
    • 概念和使用
    • 类属性 就是给 类对象 中定义的 属性
    • 通常用来记录与这个类相关 的特征
    • 类属性 不会用于 记录 具体对象的特征
    • 类的获取机制
    • 在 python中 属性的获取存在一个 向上查找机制

    • 因此,要访问类属性有两种方式:
    • 类名.类属性
    • 对象.类属性 (不推荐)
    • 注意:
    • 如果使用 对象.类属性 = 值 **赋值语句,只会给对象添加一个属性,而不会影响到类属性的值**
  • 类方法和静态方法

    • 类方法
    • 类属性 就是针对 类对象 定义的属性
    • 使用 赋值语句 在 class关键字 下方可以定义 类属性
    • 类属性 用于记录 与这个类相关 的特征
    • 类方法 就是记录 与这个类相关 的方法
    • 在 类方法 内部可以直接访问类属性 或者调用其他的类方法
    • 语法

    • 类方法需要用修饰器@classmethod来标识,告诉解释器这是一个类方法
    • 类方法的 第一个参数 应该是 cls
    • 由 哪一个类调用的方法,方法内的 cls 就是哪一个类的引用
    • 这个参数和 实例方法 的第一个参数和 self 类似
    • 提示使用其他名称也可以,不过习惯使用 cls
    • 通过 类名,调用 类方法,调用方法时,不需要传递cls 参数
    • 在方法内部
    • 可以通过 cls,访问 类属性
    • 也可以通过cls 调用其他的类方法
    • 静态方法
    • 在开发时,如果需要在类中封装一个方法,这个方法:
    • 既 不需要 访问 实例属性 或者 调用实例方法
    • 也 不需要 访问 类属性 或者 调用类方法
    • 这个时候,可以把这个方法封装成一个静态方法
    • 语法

    • 静态方法需要用 修饰器 @staticmethod来标识,告诉解释器这是一个静态方法
    • 通过 类名,调用 静态方法
  • 方法综合

  • 单例设计模式

    • 设计模式
    • 设计模式 是 前人工作的总结和提炼,通常,被人们广泛流传的设计都是针对某一特定问题 的成熟的方案
    • 使用设计模式 是为了可重用代码、让代码更容易被他人理解、保证代码可靠性
    • 单例设计模式
    • 目的 — 让 类 创建的对象,在系统中 只有 唯一的一个实例
    • 每一次执行类名( ) 返回的对象,内存地址是相同的
    • 单例设计模式的应用场景
    • 音乐播放器
    • 回收站 对象
    • 打印机 对象
    • __new__() 方法
    • 使用类名( ) 创建对象时,Python的解释器 首先 会 调用__new__方法为对象分配空间
    • __new__是一个 由object基类提供的内置的静态方法,是要作用有两个:
    • 在内存中为对象分配空间
    • 返回 对象的引用
    • Python的解释器获得对象的引用后,将引用作为 第一个参数,传递给 __init__方法
    • 重写 new 方法的代码非常固定!
    • 重写new__方法 一定要 returnsuper().__new(cls),用来返回对象的引用
    • 否则Python的解释器 得不到分配了空间的 对象引用,就不会调用对象的初始化方法
    • 注意: __new__ 是一个静态方法,在调用时需要 主动传递 cls 参数
    • Python中的单例
    • 单例— 让 类创建的对象,在系统中 只有 唯一的一个实例--à保证 引用 的唯一性
    • 定义一个 类属性,初始值是 None ,用于记录 单例对象的引用
    • 重写 __new__ 方法
    • 如果 类属性 is None,调用父类方法:__new__ 分配空间,并在类属性中记录结果
    • 返回 类属性 中记录的 对象引用
    • 只执行一次初始化工作
    • 在每次使用类名( ) 创建对象时,Python的解释器都会自动调用两个方法:
    • __new__分配空间
    • __init__ 对象初始化
    • 在对__new__方法改造后,每次都会得到第一次被创建对象的引用
    • 但是:初始化方法还会被再次调用
    • 让初始化动作只执行一次
    • 解决方法
    • 定义一个类属性 init_flag 标记是否 **执行过初始化动作,初始化值为False
    • 在__init__ 方法中,判断init_flag ,如果为 False就执行初始化动作
    • 然后将init_flag 设置为 True
    • 这样,再次自动 调用 __init__ 方法时,初始化动作就不会被再次执行了
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值