三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Python 面向对象核心实战:封装、继承、多态、抽象类、枚举、单例完整示例

Python 面向对象核心实战:封装、继承、多态、抽象类、枚举、单例完整示例

本文把 Python 面向对象高频知识点全部落地,包含:封装继承多态、多继承、抽象类、枚举类、访问权限、属性封装、单例模式(构造函数 / 装饰器两种写法),全部可直接运行。

目录

前言

1. 封装、继承、多态基础案例

2. 多继承

3. 抽象类

4. 枚举类

5. 数据的访问级别

6. 属性的封装 @property

7. 单例类:构造函数写法 + 装饰器写法

方式 1:重写__new__构造函数实现单例

方式 2:装饰器实现单例

总结速查表

拓展思考


前言

面向对象编程 (OOP) 是 Python 开发的核心,封装、继承、多态是三大基石;除此之外多继承、抽象类、枚举、访问控制、property 属性封装、单例模式,都是项目里高频出现的技术点。下面每个知识点附带可运行完整代码。

1. 封装、继承、多态基础案例

  • 封装:把属性和方法放到类内部,对外隐藏内部细节
  • 继承:子类复用父类代码,扩展自己功能
  • 多态:不同子类重写父类同名方法,调用时执行各自逻辑

python

运行

class Animal: """父类:动物""" def __init__(self, name): # 封装:把name封装到实例内部 self.name = name def speak(self): """父类方法,留给子类重写""" raise NotImplementedError("子类必须实现speak方法") class Dog(Animal): def speak(self): print(f"{self.name}:汪汪汪") class Cat(Animal): def speak(self): print(f"{self.name}:喵喵喵") # 多态:同一个方法,不同对象表现不同行为 def animal_sound(animal: Animal): animal.speak() if __name__ == "__main__": dog = Dog("小狗") cat = Cat("小猫") animal_sound(dog) animal_sound(cat)

运行输出

plaintext

小狗:汪汪汪 小猫:喵喵喵

2. 多继承

Python 支持一个类同时继承多个父类,注意 MRO 方法解析顺序。

python

运行

class A: def func(self): print("A类的func") class B: def func(self): print("B类的func") # 多继承:同时继承A、B class C(A, B): pass if __name__ == "__main__": c = C() c.func() # 查看继承搜索顺序MRO print(C.__mro__)

注意:继承顺序class C(A,B),查找方法优先找 A,找不到再找 B。

3. 抽象类

抽象类强制子类必须实现指定方法,自身不能实例化。Python 使用abc模块。

python

运行

from abc import ABC, abstractmethod class BasePay(ABC): """支付抽象类,定义规范""" @abstractmethod def pay(self, money): """子类必须实现pay方法""" pass class AliPay(BasePay): def pay(self, money): print(f"支付宝支付:{money}元") class WechatPay(BasePay): def pay(self, money): print(f"微信支付:{money}元") if __name__ == "__main__": # base = BasePay() # 抽象类不能实例化,会报错 ali = AliPay() ali.pay(100) wechat = WechatPay() wechat.pay(200)

4. 枚举类

枚举用来定义一组固定常量,避免魔法数字,使用enum.Enum

python

运行

from enum import Enum class StatusEnum(Enum): # 枚举常量 SUCCESS = 200 FAIL = 500 TIMEOUT = 408 if __name__ == "__main__": print(StatusEnum.SUCCESS) print(StatusEnum.SUCCESS.name) print(StatusEnum.SUCCESS.value) # 遍历所有枚举 for item in StatusEnum: print(item.name, item.value)

5. 数据的访问级别

Python 没有真正私有,靠命名约定区分访问权限:

  1. public:普通属性,外部随便访问
  2. _protected单下划线:保护,约定不要外部直接访问
  3. __private双下划线:私有,会发生名字重整,外部不能直接访问

python

运行

class Person: def __init__(self): self.name = "张三" # 公开 self._age = 20 # 保护 self.__id_card = "123456" # 私有 if __name__ == "__main__": p = Person() print(p.name) print(p._age) # print(p.__id_card) # 直接访问私有属性报错 # 实际被重命名为 _Person__id_card,仅做演示,不建议这么写 print(p._Person__id_card)

约定:单下划线_xxx不要在类外部读写;双下划线__xxx为私有,禁止外部访问。

6. 属性的封装 @property

使用@property把方法伪装成属性,实现 getter、setter,对属性赋值做校验,完成属性封装。

python

运行

class Student: def __init__(self): self.__score = 0 @property def score(self): """getter 获取分数""" return self.__score @score.setter def score(self, value): """setter 设置分数,增加校验逻辑""" if not isinstance(value, int): raise ValueError("分数必须是整数") if 0 <= value <= 100: self.__score = value else: raise ValueError("分数必须在0‑100之间") if __name__ == "__main__": s = Student() s.score = 88 print(s.score) # s.score = 200 # 会抛出异常

7. 单例类:构造函数写法 + 装饰器写法

单例:整个程序中,这个类只能有一个实例对象

方式 1:重写__new__构造函数实现单例

python

运行

class SingletonNew: _instance = None def __new__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance if __name__ == "__main__": obj1 = SingletonNew() obj2 = SingletonNew() print(obj1 is obj2) # True,同一个对象

方式 2:装饰器实现单例

python

运行

def singleton_decorator(cls): instance = {} def wrapper(*args, **kwargs): if cls not in instance: instance[cls] = cls(*args, **kwargs) return instance[cls] return wrapper @singleton_decorator class SingletonDecorator: pass if __name__ == "__main__": a1 = SingletonDecorator() a2 = SingletonDecorator() print(a1 is a2) # True

总结速查表

表格

知识点核心要点
封装把属性方法封装在类内部,对外隐藏细节
继承子类复用父类代码,class Son(Father)
多态不同子类重写同一方法,调用表现不同行为
多继承class C(A,B),MRO 决定方法查找顺序
抽象类ABC+@abstractmethod,强制子类实现方法,不能实例化
枚举类Enum,管理固定常量,消除魔法数字
访问级别公开、_保护__私有,命名约定控制访问
属性封装@property,把方法当属性,做赋值校验
单例__new__重写 / 装饰器,保证全局唯一实例

拓展思考

  1. 多继承场景下 MRO 顺序怎么看?类名.__mro__
  2. @property 除了 setter,还有 deleter 删除属性
  3. 单例模式在多线程下会有线程安全问题,需要加锁。
← 返回列表