30天学会Python编程:8. Python面向对象编程
8.1 OOP基础概念
8.1.1 面向对象三大特性
8.1.2 类与对象关系
核心概念:
- 类(Class):对象的蓝图/模板
- 对象(Object):类的具体实例
- 属性(Attribute):对象的状态/数据
- 方法(Method):对象的行为/功能
类比说明:
类 → 饼干模具
对象 → 用模具制作的饼干
属性 → 饼干的形状、颜色
方法 → 饼干可以被吃掉、装饰
8.2 类定义与使用
8.2.1 基本类定义
语法结构:
class ClassName:
"""类文档字符串"""
class_attribute = value # 类属性
def __init__(self, params):
"""构造方法"""
self.instance_attr = params # 实例属性
def method(self):
"""实例方法"""
# 方法体
8.2.2 案例
class BankAccount:
"""银行账户类"""
interest_rate = 0.03 # 类属性(所有账户共享)
def __init__(self, owner, balance=0):
"""初始化账户"""
self.owner = owner # 实例属性
self.balance = balance
def deposit(self, amount):
"""存款"""
self.balance += amount
return self.balance
def withdraw(self, amount):
"""取款"""
if amount > self.balance:
raise ValueError("余额不足")
self.balance -= amount
return self.balance
# 使用示例
account = BankAccount("Alice", 1000)
account.deposit(500)
print(f"{account.owner}的余额: {account.balance}")
8.3 继承与多态
8.3.1 继承实现
基本语法:
class ChildClass(ParentClass):
# 子类特有属性和方法
pass
继承示例:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("子类必须实现此方法")
class Dog(Animal):
def speak(self):
return f"{self.name}说: 汪汪!"
class Cat(Animal):
def speak(self):
return f"{self.name}说: 喵喵~"
# 多态演示
animals = [Dog("阿黄"), Cat("小花")]
for animal in animals:
print(animal.speak())
8.3.2 方法重写
class SmartAccount(BankAccount):
"""智能账户(继承自BankAccount)"""
def withdraw(self, amount):
"""重写取款方法,增加短信通知"""
result = super().withdraw(amount) # 调用父类方法
print(f"短信通知: 取出{amount}元,余额{result}元")
return result
8.4 特殊方法与运算符重载
8.4.1 常用特殊方法
表8-1 Python常用魔术方法
方法 | 描述 | 调用时机 |
__init__ | 构造方法 | 对象创建时 |
__str__ | 字符串表示 | str(obj)/print(obj) |
__repr__ | 解释器表示 | repr(obj) |
__len__ | 长度 | len(obj) |
__getitem__ | 索引访问 | obj[key] |
__add__ | 加法运算 | obj + other |
8.4.2 运算符重载示例
class Vector:
"""二维向量类"""
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
"""向量加法"""
return Vector(self.x + other.x, self.y + other.y)
def __mul__(self, scalar):
"""向量数乘"""
return Vector(self.x * scalar, self.y * scalar)
def __str__(self):
return f"Vector({self.x}, {self.y})"
# 使用示例
v1 = Vector(2, 3)
v2 = Vector(1, 4)
print(v1 + v2) # Vector(3, 7)
print(v1 * 3) # Vector(6, 9)
8.5 属性控制
8.5.1 属性装饰器
class Temperature:
def __init__(self, celsius):
self._celsius = celsius # 内部存储
@property
def celsius(self):
"""摄氏温度属性"""
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("温度不能低于绝对零度")
self._celsius = value
@property
def fahrenheit(self):
"""只读的华氏温度属性"""
return self._celsius * 9/5 + 32
# 使用示例
temp = Temperature(25)
print(temp.fahrenheit) # 77.0
temp.celsius = 30 # 调用setter方法
8.5.2 描述符协议
class PositiveNumber:
"""正数描述符"""
def __set_name__(self, owner, name):
self.name = name
def __get__(self, obj, objtype):
return obj.__dict__.get(self.name, 0)
def __set__(self, obj, value):
if value <= 0:
raise ValueError("必须为正数")
obj.__dict__[self.name] = value
class Circle:
radius = PositiveNumber() # 描述符实例
def __init__(self, radius):
self.radius = radius # 调用描述符__set__
# 使用示例
c = Circle(5)
print(c.radius) # 5
c.radius = 10 # 正常
c.radius = -1 # ValueError
8.6 类高级特性
8.6.1 类方法与静态方法
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def from_string(cls, date_str):
"""类方法作为替代构造函数"""
year, month, day = map(int, date_str.split('-'))
return cls(year, month, day)
@staticmethod
def is_valid(date_str):
"""静态方法-与类相关但不依赖实例"""
try:
year, month, day = map(int, date_str.split('-'))
return month <= 12 and day <= 31
except:
return False
# 使用示例
date = Date.from_string("2023-07-20")
print(Date.is_valid("2023-02-30")) # False
8.6.2 抽象基类
from abc import ABC, abstractmethod
class Shape(ABC):
"""形状抽象基类"""
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
class Circle(Shape):
"""实现抽象方法"""
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radius
# 不能实例化抽象类
# shape = Shape() # 报错
circle = Circle(5) # 正常
8.7 综合应用举例
案例1:电商商品系统
class Product:
"""商品基类"""
def __init__(self, name, price, stock):
self.name = name
self.price = price
self.stock = stock
def apply_discount(self, percent):
"""应用折扣"""
self.price *= (1 - percent/100)
def __str__(self):
return f"{self.name} - yen{self.price:.2f} (库存: {self.stock})"
class DigitalProduct(Product):
"""数码商品"""
def __init__(self, name, price, stock, license_key):
super().__init__(name, price, stock)
self.license_key = license_key
def activate(self, user):
"""激活许可证"""
print(f"{user} 已激活产品 {self.name}, 许可证: {self.license_key}")
class ShoppingCart:
"""购物车类"""
def __init__(self):
self.items = []
def add_item(self, product, quantity=1):
"""添加商品"""
if quantity > product.stock:
raise ValueError("库存不足")
self.items.append((product, quantity))
def total(self):
"""计算总价"""
return sum(p.price * q for p, q in self.items)
def checkout(self):
"""结算"""
total = self.total()
print(f"结算完成,总计: yen{total:.2f}")
for product, quantity in self.items:
product.stock -= quantity
self.items = []
# 使用示例
iphone = DigitalProduct("iPhone 14", 6999, 10, "XYZ-123-ABC")
book = Product("Python编程", 99, 50)
cart = ShoppingCart()
cart.add_item(iphone)
cart.add_item(book, 2)
cart.checkout()
print(iphone.stock) # 9
案例2:游戏角色系统
class Character:
"""游戏角色基类"""
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
self.skills = []
def take_damage(self, damage):
"""受到伤害"""
self.health = max(0, self.health - damage)
print(f"{self.name}受到{damage}点伤害,剩余生命: {self.health}")
return self.health <= 0
def use_skill(self, skill, target):
"""使用技能"""
if skill not in self.skills:
print(f"技能{skill}不存在")
return False
damage = self.attack + skill.damage
print(f"{self.name}对{target.name}使用{skill.name}!")
return target.take_damage(damage)
class Skill:
"""技能类"""
def __init__(self, name, damage, cost):
self.name = name
self.damage = damage
self.cost = cost
def __str__(self):
return f"{self.name}(伤害:{self.damage}, 消耗:{self.cost})"
class Warrior(Character):
"""战士职业"""
def __init__(self, name):
super().__init__(name, health=150, attack=20)
self.skills = [
Skill("重击", 15, 10),
Skill("旋风斩", 30, 25)
]
class Mage(Character):
"""法师职业"""
def __init__(self, name):
super().__init__(name, health=100, attack=30)
self.skills = [
Skill("火球术", 40, 20),
Skill("冰冻术", 25, 15)
]
# 战斗演示
hero = Warrior("英雄")
enemy = Mage("邪恶法师")
print(f"战斗开始: {hero.name} vs {enemy.name}")
hero.use_skill(hero.skills[1], enemy) # 旋风斩
enemy.use_skill(enemy.skills[0], hero) # 火球术
8.8 学习路线图
8.9 学习总结
- 核心要点:
- 理解类与对象的关系
- 掌握继承与多态的实现
- 熟练使用特殊方法
- 理解属性访问控制机制
- 实践建议:
- 遵循单一职责原则设计类
- 优先使用组合而非继承
- 合理使用属性装饰器
- 为重要方法添加类型注解
- 进阶方向:
- 元类编程
- 对象序列化
- 多继承与MRO
- 设计模式应用
- 常见陷阱:
- 混淆类属性与实例属性
- 错误的重写方法签名
- 浅拷贝导致的共享状态
- 过度使用继承导致紧耦合
持续更新Python编程学习日志与技巧,敬请关注!