目录

  • 私有属性和私有方法
    • 01. 应用场景及定义方式
    • 02. 伪私有属性和私有方法(科普)
  • 继承
    • 01. 单继承
      • 1.1 继承的概念、语法和特点
        • 1) 继承的语法
        • 2) 专业术语
        • 3) 继承的传递性
      • 1.2 方法的重写
        • 应用场景
          • 1) 覆盖父类的方法
          • 2) 对父类方法进行 扩展
        • 关于 `super`
      • 1.3 父类的 私有属性 和 私有方法
    • 02. 多继承
      • 2.1 多继承的使用注意事项
        • Python 中的 MRO —— 方法搜索顺序
      • 2.2 新式类与旧式(经典)类
  • 多态
    • 面向对象三大特性
      • 多态案例:
  • 类属性和类方法
    • 01. 类的结构
      • 1.1 术语 —— 实例
      • 1.2 类是一个特殊的对象
    • 02. 类属性和实例属性
      • 2.1 概念和使用
      • 2.2 属性的获取机制(科普)
    • 03. 类方法和静态方法
      • 3.1 类方法
      • 3.2 静态方法
        • 方法综合案例:
  • 单例
    • 01. 单例设计模式
      • 单例设计模式的应用场景
    • 02. `__new__` 方法
    • 03. Python 中的单例
      • 只执行一次初始化工作

私有属性和私有方法


01. 应用场景及定义方式


应用场景

  • 在实际开发中,对象某些属性或方法 可能只希望 在对象的内部被使用,而 不希望在外部被访问到
  • 私有属性 就是 对象 不希望公开的 属性
  • 私有方法 就是 对象 不希望公开的 方法

定义方式

  • 定义属性或方法时,在 属性名或者方法名前 增加 两个下划线,定义的就是 私有 属性或方法
class Women:
​def __init__(self, name):
​self.name = name# 不要问女生的年龄self.__age = 18
​def __secret(self):print("我的年龄是 %d" % self.__age)
​
​
xiaofang = Women("小芳")
# 私有属性,外部不能直接访问
# print(xiaofang.__age)
​
# 私有方法,外部不能直接调用
# xiaofang.__secret()

02. 伪私有属性和私有方法(科普)


提示:在日常开发中,不要使用这种方式,访问对象的 私有属性 或 私有方法

Python 中,并没有 真正意义私有

  • 在给 属性、方法 命名时,实际是对 名称 做了一些特殊处理,使得外界无法访问到
  • 处理方式:在 名称 前面加上 _类名 => _类名__名称
# 私有属性,外部不能直接访问到
print(xiaofang._Women__age)
​
# 私有方法,外部不能直接调用
xiaofang._Women__secret()

继承


面向对象三大特性:

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

01. 单继承


1.1 继承的概念、语法和特点

继承的概念子类 拥有 父类 的所有 方法属性

1) 继承的语法

class 类名(父类名):
​pass
  • 子类 继承自 父类,可以直接 享受 父类中已经封装好的方法,不需要再次开发
  • 子类 中应该根据 职责,封装 子类特有的 属性和方法

2) 专业术语

  • Dog 类是 Animal 类的子类Animal 类是 Dog 类的父类Dog 类从 Animal继承
  • Dog 类是 Animal 类的派生类Animal 类是 Dog 类的基类Dog 类从 Animal派生

3) 继承的传递性

  • C 类从 B 类继承,B 类又从 A 类继承
  • 那么 C 类就具有 B 类和 A 类的所有属性和方法

子类 拥有 父类 以及 父类的父类 中封装的所有 属性方法

1.2 方法的重写

  • 子类 拥有 父类 的所有 方法属性
  • 子类 继承自 父类,可以直接 享受 父类中已经封装好的方法,不需要再次开发
应用场景
  • 父类 的方法实现不能满足子类需求时,可以对方法进行 重写(override)

重写 父类方法有两种情况:

  1. 覆盖 父类的方法
  2. 对父类方法进行 扩展
1) 覆盖父类的方法
  • 如果在开发中,父类的方法实现子类的方法实现,完全不同
  • 就可以使用 覆盖 的方式,在子类中 重新编写 父类的方法实现

具体的实现方式,就相当于在 子类中 定义了一个 和父类同名的方法并且实现

重写之后,在运行时,只会调用 子类中重写的方法,而不再会调用 父类封装的方法

2) 对父类方法进行 扩展
  • 如果在开发中,子类的方法实现中包含父类的方法实现

    • 父类原本封装的方法实现子类方法的一部分
  • 就可以使用扩展的方式
    1. 在子类中 重写 父类的方法
    2. 在需要的位置使用 super().父类方法 来调用父类方法的执行
    3. 代码其他的位置针对子类的需求,编写 子类特有的代码实现
关于 super
  • Pythonsuper 是一个 特殊的类
  • super() 就是使用 super 类创建出来的对象
  • 最常 使用的场景就是在 重写父类方法时,调用 在父类中封装的方法实现

提示

  • 在开发时,父类名super() 两种方式不要混用
  • 如果使用 当前子类名 调用方法,会形成递归调用,出现死循环

1.3 父类的 私有属性 和 私有方法

  1. 子类对象 不能 在自己的方法内部,直接 访问 父类的 私有属性私有方法
  2. 子类对象 可以通过 父类公有方法 间接 访问到 私有属性私有方法
  • 私有属性、方法 是对象的隐私,不对外公开,外界 以及 子类 都不能直接访问
  • 私有属性、方法 通常用于做一些内部的事情

示例

  • B 的对象不能直接访问 __num2 属性
  • B 的对象不能在 demo 方法内访问 __num2 属性
  • B 的对象可以在 demo 方法内,调用父类的 test 方法
  • 父类的 test 方法内部,能够访问 __num2 属性和 __test 方法

02. 多继承


概念

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

语法

class 子类名(父类名1, 父类名2...)pass

2.1 多继承的使用注意事项

提示:
开发时,应该尽量避免这种容易产生混淆的情况! —— 如果 父类之间 存在 同名的属性或者方法,应该 尽量避免 使用多继承

Python 中的 MRO —— 方法搜索顺序

  • Python 中针对 提供了一个 内置属性 __mro__ 可以查看 方法 搜索顺序
  • MRO 是 method resolution order,主要用于 在多继承时判断 方法、属性 的调用 路径
print(C.__mro__)

输出结果

(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
  • 在搜索方法时,是按照 __mro__ 的输出结果 从左至右 的顺序查找的
  • 如果在当前类中 找到方法,就直接执行,不再搜索
  • 如果 没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索
  • 如果找到最后一个类,还没有找到方法,程序报错

2.2 新式类与旧式(经典)类

objectPython 为所有对象提供的 基类,提供有一些内置的属性和方法,可以使用 dir 函数查看

  • 新式类:以 object 为基类的类,推荐使用
  • 经典类:不以 object 为基类的类,不推荐使用
  • Python 3.x 中定义类时,如果没有指定父类,会 默认使用 object 作为该类的 基类 —— Python 3.x 中定义的类都是 新式类
  • Python 2.x 中定义类时,如果没有指定父类,则不会以 object 作为 基类

新式类经典类 在多继承时 —— 会影响到方法的搜索顺序

为了保证编写的代码能够同时在 Python 2.xPython 3.x 运行! 今后在定义类时,如果没有父类,建议统一继承自 object

规范格式如下

class 类名(object):pass

多态


面向对象三大特性

  1. 封装根据职责将属性和方法封装到一个抽象的类中

    • 定义类的准则
  2. 继承实现代码的重用,相同的代码不需要重复的编写

    1. 设计类的技巧
    2. 子类针对自己特有的需求,编写特定的代码
  3. 多态 不同的 子类对象 调用相同的 父类方法,产生不同的执行结果

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

多态案例:


需求

  • 在Dog类中封装方法game

    • 普通狗只是简单的玩耍
  • 定义XiaoTianDog继承自Dog,并且重写game方法
    • 哮天犬需要在天上玩耍
  • 定义Person类,并且封装一个和狗玩的方法
    • 在方法内部,直接让 狗对象 调用 game 方法


案例逻辑

  • Person类中只需要让狗对象调用game方法,而不关心具体是什么狗

    • game 方法是在 Dog 父类中定义的
  • 在程序执行时,传入不同的 狗对象 实参,就会产生不同的执行效果

多态 更容易编写出出通用的代码,做出通用的编程,以适应需求的不断变化!

class Dog(object):
​def __init__(self, name):self.name = name
​def game(self):print("%s 蹦蹦跳跳的玩耍..." % self.name)
​
​
class XiaoTianDog(Dog):
​def game(self):print("%s 飞到天上去玩耍..." % self.name)
​
​
class Person(object):
​def __init__(self, name):self.name = name
​def game_with_dog(self, dog):
​print("%s 和 %s 快乐的玩耍..." % (self.name, dog.name))
​# 让狗玩耍dog.game()
​
​
# 1. 创建一个狗对象
# wangcai = Dog("旺财")
wangcai = XiaoTianDog("飞天旺财")
​
# 2. 创建一个小明对象
xiaoming = Person("小明")
​
# 3. 让小明调用和狗玩的方法
xiaoming.game_with_dog(wangcai)

类属性和类方法


01. 类的结构


1.1 术语 —— 实例

  • 使用面相对象开发,第 1 步 是设计

  • 使用类名()创建对象,创建对象的动作有两步:

    • 1)在内存中为对象 分配空间
    • 2)调用初始化方法 __init__对象初始化
  • 对象创建后,内存 中就有了一个对象的 实实在在 的存在 —— 实例

因此,通常也会把:

  1. 创建出来的 对象 叫做 实例
  2. 创建对象的 动作 叫做 实例化
  3. 对象的属性 叫做 实例属性
  4. 对象调用的方法 叫做 实例方法

在程序执行时:

  1. 对象各自拥有自己的 实例属性
  2. 调用对象方法,可以通过self.
    • 访问自己的属性
    • 调用自己的方法

1.2 类是一个特殊的对象

Python一切皆对象

  • class AAA: 定义的类属于 类对象
  • obj1 = AAA() 属于 实例对象
  • 在程序运行时, 同样 会被加载到内存
  • Python 中, 是一个特殊的对象 —— 类对象
  • 在程序运行时,类对象 在内存中 只有一份,使用 一个类 可以创建出 很多个对象实例
  • 除了封装实例的属性和方法外,类对象还可以拥有自己的属性和方法
    1. 类属性
    2. 类方法
  • 通过 类名. 的方式可以 访问类的属性 或者 调用类的方法

02. 类属性和实例属性


2.1 概念和使用

  • 类属性 就是给 类对象 中定义的 属性
  • 通常用来记录 与这个类相关 的特征
  • 类属性 不会用于记录 具体对象的特征

示例需求

  • 定义一个 工具类
  • 每件工具都有自己的 name
  • 需求 —— 知道使用这个类,创建了多少个工具对象?
class Tool(object):
​# 使用赋值语句,定义类属性,记录创建工具对象的总数count = 0
​def __init__(self, name):self.name = name
​# 针对类属性做一个计数+1Tool.count += 1
​
​
# 创建工具对象
tool1 = Tool("斧头")
tool2 = Tool("榔头")
tool3 = Tool("铁锹")
​
# 知道使用 Tool 类到底创建了多少个对象?
print("现在创建了 %d 个工具" % Tool.count)

2.2 属性的获取机制(科普)

  • Python属性的获取 存在一个 向上查找机制
  • 因此,要访问类属性有两种方式:
    1). 类名.类属性
    2). 对象.类属性 (不推荐)

注意

  • 如果使用 对象.类属性 = 值 赋值语句,只会 给对象添加一个属性,而不会影响到 类属性的值

03. 类方法和静态方法


3.1 类方法

  • 类属性就是针对类对象定义的属性

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

语法如下

@classmethod
def 类方法名(cls):pass
  • 类方法需要用 修饰器 @classmethod 来标识,告诉解释器这是一个类方法

  • 类方法的第一个参数应该是cls

    • 哪一个类 调用的方法,方法内的 cls 就是 哪一个类的引用
    • 这个参数和 实例方法 的第一个参数是 self 类似
    • 提示 使用其他名称也可以,不过习惯使用 cls
  • 通过 类名. 调用 类方法调用方法时,不需要传递 cls 参数

  • 在方法内部

    • 可以通过 cls. 访问类的属性
    • 也可以通过 cls. 调用其他的类方法

示例需求

  • 定义一个 工具类
  • 每件工具都有自己的 name
  • 需求 —— 在 封装一个 show_tool_count 的类方法,输出使用当前这个类,创建的对象个数
@classmethod
def show_tool_count(cls):"""显示工具对象的总数"""print("工具对象的总数 %d" % cls.count)

在类方法内部,可以直接使用 cls 访问 类属性 或者 调用类方法

3.2 静态方法

  • 在开发时,如果需要在 中封装一个方法,这个方法:

    • 不需要 访问 实例属性 或者调用 实例方法
    • 不需要 访问 类属性 或者调用 类方法
  • 这个时候,可以把这个方法封装成一个 静态方法

语法如下

@staticmethod
def 静态方法名():pass
  • 静态方法 需要用 修饰器 @staticmethod 来标识,告诉解释器这是一个静态方法
  • 通过 类名. 调用 静态方法

案例:

class Dog(object):# 狗对象计数dog_count = 0@staticmethoddef run():# 不需要访问实例属性也不需要访问类属性的方法print("狗在跑...")
​def __init__(self, name):self.name = name

方法综合案例:

需求

  1. 设计一个 Game

  2. 属性:
    1). 定义一个 类属性 top_score 记录游戏的 历史最高分
    2). 定义一个 实例属性 player_name 记录 当前游戏的玩家姓名

  3. 方法:
    1). 静态方法 show_help 显示游戏帮助信息
    2).类方法 show_top_score 显示历史最高分
    3).实例方法 start_game 开始当前玩家的游戏

  4. 主程序步骤

    1. 查看帮助信息
    2. 查看历史最高分
    3. 创建游戏对象,开始游戏

    代码逻辑思路

  • 实例方法—— 方法内部需要访问实例属性

    • 实例方法 内部可以使用 类名. 访问类属性
  • 类方法 —— 方法内部 需要访问 类属性

  • 静态方法 —— 方法内部,不需要访问 实例属性类属性

案例完整代码

class Game(object):
​# 游戏最高分,类属性top_score = 0
​@staticmethoddef show_help():print("帮助信息:让僵尸走进房间")@classmethoddef show_top_score(cls):print("游戏最高分是 %d" % cls.top_score)
​def __init__(self, player_name):self.player_name = player_name
​def start_game(self):print("[%s] 开始游戏..." % self.player_name)# 使用类名.修改历史最高分Game.top_score = 999
​
# 1. 查看游戏帮助
Game.show_help()
​
# 2. 查看游戏最高分
Game.show_top_score()
​
# 3. 创建游戏对象,开始游戏
game = Game("小明")
​
game.start_game()
​
# 4. 游戏结束,查看游戏最高分
Game.show_top_score()

单例


01. 单例设计模式


  • 设计模式

    • 设计模式前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对 某一特定问题 的成熟的解决方案
    • 使用 设计模式 是为了可重用代码、让代码更容易被他人理解、保证代码可靠性
  • 单例设计模式
    • 目的 —— 让 创建的对象,在系统中 只有 唯一的一个实例
    • 每一次执行 类名() 返回的对象,内存地址是相同的

单例设计模式的应用场景

  • 音乐播放 对象
  • 回收站 对象
  • 打印机 对象
  • ……

02. __new__ 方法


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

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

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

    示例代码
class MusicPlayer(object):
​def __new__(cls, *args, **kwargs):# 如果不返回任何结果,return super().__new__(cls)
​def __init__(self):print("初始化音乐播放对象")
​
player = MusicPlayer()
​
print(player)

03. Python 中的单例


  • 单例—— 让类创建的对象,在系统中只有唯一的一个实例
  1. 定义一个 类属性,初始值是 None,用于记录 单例对象的引用
  2. 重写 __new__ 方法
  3. 如果 类属性 is None,调用父类方法分配空间,并在类属性中记录结果
  4. 返回 类属性 中记录的 对象引用
class MusicPlayer(object):
​# 定义类属性记录单例对象引用instance = None
​def __new__(cls, *args, **kwargs):
​# 1. 判断类属性是否已经被赋值if cls.instance is None:cls.instance = super().__new__(cls)
​# 2. 返回类属性的单例引用return cls.instance

只执行一次初始化工作

  • 在每次使用类名()创建对象时,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 = 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)

面向对象(三、类私有属性和私有方法)相关推荐

  1. Python类中的私有属性和私有方法

    Python类中的私有属性和私有方法 Python是面向对象的语言,在Python里一切皆对象,所以大部分情况下,我们都是通过类的方式来编程. 但是Python中的属性和方法在类的外部默认是可以访问的 ...

  2. 传智播客python笔记_python传智播客笔记--第十天:隐藏属性,私有属性,私有方法,__del__方法,类的继承,类中方法的重写...

    封装,继承,多态 隐藏属性,私有属性,私有方法,__del__方法,类的继承,类中方法的重写 -**************************************************** ...

  3. Python中的类属性和类方法(静态方法、私有属性和私有方法)

    一.类属性和类方法 类的方法 在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数 代码块: class Student(object ...

  4. python 类 公有属性、私有属性、公有方法、私有方法

    python 类 公有属性.私有属性.公有方法.私有方法 #!/usr/bin/env python # -*- encoding: utf-8 -*- """ @Int ...

  5. python_day6_面向对象的介绍/构造函数/类变量和实例变量/析构函数/私有属性和私有方法/继承、多继承和继承实例/多态

    python_面向对象的介绍/构造函数/类变量和实例变量/析构函数/私有属性和私有方法/继承.多继承和继承实例/多态 在这里得感谢,老师Alex金角大王(路飞学城IT) Python(给兄弟们挂个

  6. 封装详解,private,修改私有属性get/set方法,类和对象总结

    方法,属性,有参与无参构造函数,对私有属性private的访问get/set方法都在类中:在我们的项目中只有一个实现类main,在main中将类实例化为对象,通过对象来调用类中的方法,属性,有参与无参 ...

  7. 20_python基础—面向对象-私有属性和私有方法

    文章目录 一.应用场景及定义方式 二.伪私有属性和私有方法(科普) 一.应用场景及定义方式 应用场景 在实际开发中,对象 的 某些属性或方法 可能只希望 在对象的内部被使用,而 不希望在外部被访问到 ...

  8. Python之面向对象 私有属性和私有方法

    私有属性和私有方法 应用场景及定义方式 应用场景 在实际开发中,对象 的 某些属性或方法 可能只希望 在对象的内部被使用,而 不希望在外部被访问到 私有属性 就是 对象 不希望公开的 属性 私有方法 ...

  9. python中的类属性和类方法_Python 面向对象,类的属性和 类的方法

    面向对象,类的属性和 类的方法 面向对象 类和对象 Python类定义 类属性 类方法 面向过程和面向对象 面向过程 和 面向对象 编程 面向过程 编程:函数式编程,C程序,shell等 面向对象 编 ...

最新文章

  1. linux7怎样搭建zabbix,Centos7.0 搭建Zabbix环境
  2. mysql 5.7 mts_MySQL:MTS和mysqldump死锁
  3. 程序员遇到的奇葩bug大集锦,硬盘开光很有必要!
  4. CentOS安装nmap端口查看工具
  5. pythonplc曲线_PLC的编程策略:面向对象编程和梯形图逻辑之比较
  6. 制作Docker镜像的两种方式
  7. 找不到图片素材,看这里
  8. 【C++ 与 STL】双端队列:deque
  9. 剑指offer(C++)-JZ22:链表中倒数最后k个结点(数据结构-链表)
  10. CCF NOI1016 计算天数
  11. Context Menu控件
  12. html 跑马灯效果 源代码,跑马灯效果.html
  13. 发言倒计时器_单面会议计时器 会议发言倒计时器
  14. 个推科普漫画,解读《女心理师》中的智能语音识别系统
  15. 汇编语言必看书籍推荐
  16. 学学拍照姿势!(别只懂得插裤袋,哈哈)
  17. 真实数据揭秘游戏主播能否月入100万
  18. 论文笔记 EMNLP 2020|Edge-Enhanced Graph Convolution Networks for Event Detection with Syntactic Relation
  19. 36氪2022年Q3总收入同比增长两位数超预期,连续第四个季度盈利,广告收入同比增长20%
  20. RxJava操作符学习APP

热门文章

  1. 【ae】抠图之:线性颜色键,去除背景色,与其他图层溶合
  2. SharePreferences数据丢失问题的处理和解决方案
  3. 【神界原罪2】ce修改
  4. 浅谈Swift和Objective-C之间的那点事。。。
  5. mac mysql 查看用户_Mac 最全 Mysql忘记用户名和密码如何处理-Go语言中文社区
  6. 基于idea-SSM的房产中介房屋租赁出租出售交易平台(javaweb-php-asp.netC#-j2ee-springboot)
  7. 河海大学MBA陈钢教授 开学讲座
  8. note2 android8.0,小米Android 8.0再添丁!小米Note 2国际版MIUI9获推送
  9. 第七章 凹凸映射 渐变纹理 遮罩纹理
  10. 初识「零知识」与「证明」