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原则
-
单一职责原则(SRP):一个类只负责一件事
-
开闭原则(OCP):对扩展开放,对修改关闭
-
里氏替换原则(LSP):子类应该能替换父类
-
接口隔离原则(ISP):客户端不应依赖不需要的接口
-
依赖倒置原则(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>'
如果您觉得本文章对您有帮助,别忘了点赞、收藏加关注,更多干货内容将持续发布,您的支持就是作者更新最大的动力。本专栏将持续更新,有任何问题都可以在评论区讨论