python面向对象的知识梳理

面向对象(Object Oriented Programming

三个基本特征:

1.封装:包含两个概念,对象将变量(状态)和方法(用来改变状态或执行涉及状态的计算)集中在一个地方—即对象本身。

通过封装隐藏类的内部数据,以避免客户端(client)代码(即类外部的代码)直接进行访问。

2.继承:在创建类时,该类也可以从另一个类那里继承方法和变量。被继承的类,称为父类(parent class);继承的类则被称为子类(child class)

3.多态:为不同的基础形态(数据类型)提供相关接口的能力。(其中接口指的就是函数或者方法)

变量:

类变量:属于类对象及其创建的对象。

实例变量:实例变量属于对象。

定义属性或方法时,在 属性名或者方法名前 增加 两个下划线,定义的就是 私有 属性或方法

其中在类中的方法可以调用私有方法和变量

但是子类不能访问父类的私有方法及私有变量

class Dog(object):
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    def eat(self):
        print('eating',self.__age)
        self.__eating_food()

    def __eating_food(self):
        print("food", self.name)


if __name__ == '__main__':
    d = Dog("tom", 15)# eating 15
    d.eat()# food tom

  

但是Python 中,并没有 真正意义 的 私有

给 属性、方法 命名时,实际是对 名称 做了一些特殊处理,使得外界无法访问到处理方式:在 名称 前面加上 _类名 => _类名__名称(例如d_Dog_age)

单例模式

设计模式

  • 设计模式前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对 某一特定问题 的成熟的解决方案
  • 使用 设计模式 是为了可重用代码、让代码更容易被他人理解、保证代码可靠性

 

单例设计模式

  • 目的 —— 让 创建的对象,在系统中 只有 唯一的一个实例
  • 每一次执行 类名() 返回的对象,内存地址是相同的

__new__ 方法

  • 使用 类名() 创建对象时,Python 的解释器 首先 会 调用 __new__ 方法为对象 分配空间
  • __new__ 是一个 由 object 基类提供的 内置的静态方法,主要作用有两个:
    • 1) 在内存中为对象 分配空间
    • 2) 返回 对象的引用
  • Python 的解释器获得对象的 引用 后,将引用作为 第一个参数,传递给 __init__ 方法

重写 __new__ 方法 的代码非常固定!

  • 重写 __new__ 方法 一定要 return super().__new__(cls)
  • 否则 Python 的解释器 得不到 分配了空间的 对象引用就不会调用对象的初始化方法
  • 注意:__new__ 是一个静态方法,在调用时需要 主动传递 cls 参数

Python 中的单例

  • 单例 —— 让 创建的对象,在系统中 只有 唯一的一个实例
    1. 定义一个 类属性,初始值是 None,用于记录 单例对象的引用
    2. 重写 __new__ 方法
    3. 如果 类属性 is None,调用父类方法分配空间,并在类属性中记录结果
    4. 返回 类属性 中记录的 对象引用

  

只执行一次初始化工作

  • 在每次使用 类名() 创建对象时,Python 的解释器都会自动调用两个方法:
    • __new__ 分配空间
    • __init__ 对象初始化
  • 在上一小节对 __new__ 方法改造之后,每次都会得到 第一次被创建对象的引用
  • 但是:初始化方法还会被再次调用

需求

  • 初始化动作 只被 执行一次

解决办法

  1. 定义一个类属性 init_flag 标记是否 执行过初始化动作,初始值为 False
  2. __init__ 方法中,判断 init_flag,如果为 False 就执行初始化动作
  3. 然后将 init_flag 设置为 True
  4. 这样,再次 自动 调用 __init__ 方法时,初始化动作就不会被再次执行
    class MusicPlayer(object):
    
        # 记录第一个被创建对象的引用
        instance = None
        # 记录是否执行过初始化动作
        init_flag = False
    
        def __new__(cls, *args, **kwargs):
    
            # 1. 判断类属性是否是空对象
            if cls.instance is None:
                # 2. 调用父类的方法,为第一个对象分配空间,第一次调用父类方法返回的结果用cls.instance这个变量保存
                cls.instance = super().__new__(cls)
    
            # 3. 返回类属性保存的对象引用(可以理解为第一次为对象分配的内存地址)
            return cls.instance
    
        def __init__(self):
    
            if not MusicPlayer.init_flag:
                print("初始化音乐播放器")
    
                MusicPlayer.init_flag = True
    
    
    # 创建多个对象
    player1 = MusicPlayer()
    print(player1)
    
    player2 = MusicPlayer()
    print(player2)

     

 

posted @ 2019-04-17 13:27  Yrind  阅读(172)  评论(0编辑  收藏  举报