当前位置: 首页 > news >正文

Python入门(6):面向对象编程(OOP)

目录

1. 面向对象基础概念

1.1 什么是面向对象编程?

2. 类和对象

2.1 类的定义与实例化

2.2 self关键字

3. 面向对象三大特性

3.1 封装(Encapsulation)

3.2 继承(Inheritance)

 3.3 多态(Polymorphism)

4. 高级面向对象特性

4.1 类方法和静态方法:咖啡店的故事 ☕

类方法:店长专用工具

4.2 属性装饰器:智能保险箱 🔒

传统方式 vs 属性装饰器

4.3 魔术方法

示例:让书本对象支持加法(合并页数)

 常用魔术方法分类

5. 设计模式与最佳实践

5.1 组合优于继承

5.2 SOLID原则

6. Python特有的OOP特性

6.1 多重继承

6.2 Mixin模式


1. 面向对象基础概念

1.1 什么是面向对象编程?

        面向对象编程(Object-Oriented Programming, OOP)是一种编程范式,它将数据和操作数据的方法组织为对象(Object)。Python是完全支持OOP的语言,其核心概念包括:

  • 类(Class):对象的蓝图或模板

  • 对象(Object):类的具体实例

  • 属性(Attribute):对象包含的数据

  • 方法(Method):对象能执行的操作

# 定义一个简单的类
class Dog:
    """狗类的简单示例"""
    
    def __init__(self, name):
        """初始化方法"""
        self.name = name  # 实例属性
        
    def bark(self):
        """实例方法"""
        print(f"{self.name}在汪汪叫!")

# 创建对象
my_dog = Dog("旺财")
my_dog.bark()  # 输出: 旺财在汪汪叫!

2. 类和对象

2.1 类的定义与实例化

class Person:
    """人类示例"""
    
    # 类属性 (所有实例共享)
    species = "Homo sapiens"
    
    def __init__(self, name, age):
        """构造方法,创建实例时自动调用"""
        self.name = name  # 实例属性
        self.age = age
        
    def introduce(self):
        """实例方法"""
        print(f"我叫{self.name},今年{self.age}岁。")

# 实例化对象
p1 = Person("张三", 25)
p1.introduce()  # 输出: 我叫张三,今年25岁。
print(p1.species)  # 输出: Homo sapiens

2.2 self关键字

        在类的方法中,self参数代表类的当前实例。Python会自动传递这个参数,你只需要在方法定义时声明它。

class Example:
    def method(self, arg):
        print(f"self: {self}, arg: {arg}")

e = Example()
e.method("test")  # self会自动传入

3. 面向对象三大特性

3.1 封装(Encapsulation)

        封装是将数据和方法包装在类中,并控制外部访问的机制。

class BankAccount:
    """银行账户类,展示封装概念"""
    
    def __init__(self, owner, balance=0):
        """私有属性用单下划线开头(约定,非强制)"""
        self._owner = owner
        self._balance = balance
        
    def deposit(self, amount):
        """存款方法"""
        if amount > 0:
            self._balance += amount
            print(f"存入{amount}元,当前余额: {self._balance}")
        else:
            print("存款金额必须大于0")
    
    def withdraw(self, amount):
        """取款方法"""
        if 0 < amount <= self._balance:
            self._balance -= amount
            print(f"取出{amount}元,当前余额: {self._balance}")
        else:
            print("取款金额无效")
    
    def get_balance(self):
        """获取余额(封装内部实现)"""
        return self._balance

# 使用示例
account = BankAccount("李四", 1000)
account.deposit(500)  # 存入500元,当前余额: 1500
account.withdraw(200)  # 取出200元,当前余额: 1300
print(account.get_balance())  # 1300

3.2 继承(Inheritance)

        继承允许我们定义一个新类来继承现有类的属性和方法。

class Animal:
    """动物基类"""
    
    def __init__(self, name):
        self.name = name
        
    def speak(self):
        raise NotImplementedError("子类必须实现此方法")
        # 如果子类不重写此方法,那么由子类创建的实例在调用这个方法时就会抛出上述异常

class Dog(Animal):
    """Dog类继承Animal"""
    
    def speak(self):
        return f"{self.name}说: 汪汪!"

class Cat(Animal):
    """Cat类继承Animal"""
    
    def speak(self):
        return f"{self.name}说: 喵喵!"


# 使用继承
dog = Dog("阿黄")
cat = Cat("小花")
print(dog.speak())  # 阿黄说: 汪汪!
print(cat.speak())  # 小花说: 喵喵!

如果对异常不太熟悉,请看这篇文章:Python入门(5):异常处理-CSDN博客

 3.3 多态(Polymorphism)

        多态指不同类的对象对同一消息做出不同响应

# 创建一个函数
def animal_sound(animal):
    """多态示例函数"""
    print(animal.speak())

# 传入不同子类对象(即传入不同的实例)
animal_sound(Dog("大黄"))  # 大黄说: 汪汪!
animal_sound(Cat("咪咪"))  # 咪咪说: 喵喵!

4. 高级面向对象特性

4.1 类方法和静态方法:咖啡店的故事 ☕

类方法:店长专用工具

想象你开了一家咖啡连锁店:

  • 类方法就像店长权限:可以修改所有分店的配方

  • 自动获取店铺信息:知道当前是哪家分店在调用

class CoffeeShop:
    franchise_recipe = "标准配方"  # 所有分店共用
    
    @classmethod
    def change_recipe(cls, new_recipe):
        """修改所有分店的配方"""
        cls.franchise_recipe = new_recipe  # cls自动指向当前类

# 总店修改配方
CoffeeShop.change_recipe("升级配方")
print(CoffeeShop.franchise_recipe)  # 输出:升级配方

 静态方法:店员通用工具

  • 与店铺无关的工具:比如计算找零的方法

  • 不需要知道店铺信息:就像计算器,谁都可以用

class CoffeeShop:
    @staticmethod
    def calculate_change(price, money):
        """计算找零(与店铺状态无关)"""
        return money - price if money >= price else 0

# 任何地方都能用
change = CoffeeShop.calculate_change(30, 50)
print(change)  # 输出:20

4.2 属性装饰器:智能保险箱 🔒

传统方式 vs 属性装饰器

假设你有一个存钱罐:

# 传统方式(直接访问危险)
class PiggyBank:
    def __init__(self):
        self.money = 0

bank = PiggyBank()
bank.money = -100  # 不合理!但可以随便改
# 使用属性装饰器(安全访问)
class SafePiggyBank:
    def __init__(self):
        self._money = 0  # 内部变量用下划线
    
    @property
    def money(self):
        """查看余额"""
        return self._money
    
    @money.setter
    def money(self, value):
        """存钱时的安全检查"""
        if value < 0:
            print("金额不能为负!")
            return
        self._money = value

bank = SafePiggyBank()
bank.money = 50   # 正常
bank.money = -30  # 打印警告,值不变
print(bank.money) # 输出:50

4.3 魔术方法

        魔术方法(双下划线方法)允许类自定义特定操作的行为,让自定义对象支持Python的各种语法:

示例:让书本对象支持加法(合并页数)

class Book:
    def __init__(self, title, pages):
        self.title = title
        self.pages = pages
    
    # + 运算符重载
    def __add__(self, other):
        return Book(
            f"{self.title}+{other.title}", 
            self.pages + other.pages
        )
    
    # 打印对象时显示友好信息
    def __str__(self):
        return f"《{self.title}》({self.pages}页)"

# 使用示例
book1 = Book("Python基础", 200)
book2 = Book("算法进阶", 300)
combined = book1 + book2
print(combined)  # 输出:《Python基础+算法进阶》(500页)

 常用魔术方法分类

类别方法描述
对象创建__new__实例创建时调用
__init__实例初始化时调用
__del__实例销毁时调用
对象表示__str__非正式字符串表示
__repr__正式字符串表示
运算符重载__add__/__sub__加减运算
__eq__/__lt__比较运算
__call__使实例可调用
容器行为__len__定义容器的长度
__getitem__定义索引访问
上下文管理__enter__with语句进入时调用
__exit__with语句退出时调用

 小结:什么时候用❓

特性使用场景生活比喻
类方法需要操作类级别数据店长修改所有分店的配方
静态方法工具函数,与类/实例无关店铺里的计算器
属性装饰器保护数据完整性,添加访问逻辑带密码的保险箱
魔术方法让对象支持Python内置操作给普通物品添加超能力

5. 设计模式与最佳实践

5.1 组合优于继承

class Engine:
    """引擎类"""
    def start(self):
        print("引擎启动")

class Wheel:
    """轮胎类"""
    def rotate(self):
        print("轮胎转动")

class Car:
    """使用组合而非继承"""
    def __init__(self):
        self.engine = Engine()
        self.wheels = [Wheel() for _ in range(4)]
    
    def drive(self):
        self.engine.start()
        for wheel in self.wheels:
            wheel.rotate()
        print("汽车行驶中")

# 使用组合
my_car = Car()
my_car.drive()

5.2 SOLID原则

  1. 单一职责原则(SRP):一个类只负责一件事

  2. 开闭原则(OCP):对扩展开放,对修改关闭

  3. 里氏替换原则(LSP):子类应该能替换父类

  4. 接口隔离原则(ISP):客户端不应依赖不需要的接口

  5. 依赖倒置原则(DIP):依赖抽象而非具体实现

    # 依赖倒置原则示例
    from abc import ABC, abstractmethod
    
    class Switchable(ABC):
        """抽象基类(接口)"""
        @abstractmethod
        def turn_on(self):
            pass
        
        @abstractmethod
        def turn_off(self):
            pass
    
    class LightBulb(Switchable):
        """具体实现"""
        def turn_on(self):
            print("灯泡亮了")
        
        def turn_off(self):
            print("灯泡灭了")
    
    class Fan(Switchable):
        """另一个具体实现"""
        def turn_on(self):
            print("风扇转动")
        
        def turn_off(self):
            print("风扇停止")
    
    class ElectricPowerSwitch:
        """依赖抽象而非具体类"""
        def __init__(self, device: Switchable):
            self.device = device
            self.on = False
        
        def press(self):
            if self.on:
                self.device.turn_off()
                self.on = False
            else:
                self.device.turn_on()
                self.on = True
    
    # 使用示例
    light = LightBulb()
    switch = ElectricPowerSwitch(light)
    switch.press()  # 灯泡亮了
    switch.press()  # 灯泡灭了
    
    fan = Fan()
    switch = ElectricPowerSwitch(fan)
    switch.press()  # 风扇转动
    switch.press()  # 风扇停止


6. Python特有的OOP特性

6.1 多重继承

class Flyer:
    def fly(self):
        print("飞行中")

class Swimmer:
    def swim(self):
        print("游泳中")

class FlyingFish(Flyer, Swimmer):
    """多重继承"""
    pass

fish = FlyingFish()
fish.fly()  # 飞行中
fish.swim()  # 游泳中

6.2 Mixin模式

class JsonMixin:
    """Mixin类提供JSON功能"""
    def to_json(self):
        import json
        return json.dumps(self.__dict__)

class XmlMixin:
    """Mixin类提供XML功能"""
    def to_xml(self):
        from xml.etree.ElementTree import Element, tostring
        elem = Element(type(self).__name__)
        for key, value in self.__dict__.items():
            child = Element(key)
            child.text = str(value)
            elem.append(child)
        return tostring(elem)

class Person(JsonMixin, XmlMixin):
    """使用Mixin类"""
    def __init__(self, name, age):
        self.name = name
        self.age = age

# 使用Mixin功能
p = Person("王五", 30)
print(p.to_json())  # {"name": "王五", "age": 30}
print(p.to_xml())   # b'<Person><name>王五</name><age>30</age></Person>'

如果您觉得本文章对您有帮助,别忘了点赞、收藏加关注,更多干货内容将持续发布,您的支持就是作者更新最大的动力。本专栏将持续更新,有任何问题都可以在评论区讨论

http://www.dtcms.com/a/106679.html

相关文章:

  • Smith Chart阻抗匹配
  • elasticsearch 7.17 索引模板
  • 一段式端到端自动驾驶:UniAD:Planning-oriented Autonomous Driving
  • python函数装饰器
  • (linux操作系统)环境变量
  • 【NS3-如何在NS3中模拟每个节点的本地时钟?
  • 自动获取屏幕尺寸信息的html文件
  • [图文]directed不是direct-《分析模式》漫谈50
  • 算法刷题记录——LeetCode篇(3.10) [第291~300题](持续更新)
  • 【Java中级】10章、内部类、局部内部类、匿名内部类、成员内部类、静态内部类的基本语法和细节讲解配套例题巩固理解【5】
  • 《AI大模型应知应会100篇》第7篇:Prompt Engineering基础:如何与大模型有效沟通
  • SAP BDC应用1-批量处理财务三大报表
  • Java 代理模式 详解
  • 4.2学习总结
  • Vue与React区别分析
  • 机器学习开发全流程详解:从数据到部署的完整指南
  • el-dialog实现遮罩层后面的内容也能点击
  • SqlServer整库迁移至Oracle
  • 鹧鸪云光伏仿真软件场外设计功能:构建系统级工程闭环
  • time.sleep(10)和 async 区别
  • 通信算法之251: 时频图谱spectrogram(如短时傅里叶变换STFT)
  • 数据结构——队列的实现
  • LeetCode算法题(Go语言实现)_26
  • LLM大模型之精度问题(FP16,FP32,BF16)详解与实践
  • Mapreduce的使用
  • 深入理解归并排序:分治艺术的经典实践
  • 【AI产品分享】面向图片的原始位置翻译功能
  • Redisson中BitMap位图的基本操作
  • CORS与OPTIONS请求
  • 蓝桥杯 游戏 6251 单调队列