-
目录
-
私有属性和方法
- 在实际开发中,对象 的 某些属性或方法 可能只希望在类的内部被使用,而 不希望在外部被访问到
- 私有属性 就是 对象不希望公开的 属性
- 私有方法 就是 对象不希望公开的 方法
- 定义方式
- 在 定义属性或方法时,在属性名或者方法名前 增加两个下划线,定义的就是私有 属性或方法
- 私有属性和方法在外界不能直接被访问
- 伪 私有属性和私有方法
- 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、封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中
-
类属性
- 类的结构
- 使用面向对象开发,第 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__ 方法时,初始化动作就不会被再次执行了
面向对象(进阶)
最新推荐文章于 2024-07-12 19:06:42 发布