1. 从现实世界到代码世界:类和对象的基本概念
第一次接触面向对象编程时,我常常困惑:为什么需要类和对象?直接写函数不就行了吗?直到有次需要开发一个电商系统才恍然大悟。想象你正在设计一个在线商城的商品管理系统——每个商品都有名称、价格、库存等属性,还需要计算折扣、更新库存等方法。如果只用函数,你会发现自己不断重复定义相似的变量和操作,代码很快变得难以维护。
类(Class)就是解决这个问题的蓝图。它定义了某一类事物的共同特征和行为。就像建筑设计图纸规定了房子的结构和功能,但图纸本身并不能住人。以商品为例:
python复制class Product:
def __init__(self, name, price, stock):
self.name = name # 商品名称
self.price = price # 商品价格
self.stock = stock # 库存数量
def apply_discount(self, percent):
"""应用折扣"""
return self.price * (1 - percent/100)
def update_stock(self, amount):
"""更新库存"""
self.stock += amount
对象(Object)则是根据这个蓝图创建的具体实例。就像根据同一张图纸可以建造多栋实际可住的房子:
python复制# 创建两个商品对象
phone = Product("智能手机", 5999, 100)
book = Product("Python教程", 89, 50)
# 使用对象方法
print(phone.apply_discount(10)) # 输出5399.1
book.update_stock(-2) # 卖出2本
关键理解:类是所有实例的抽象模板,而对象是内存中真实存在的数据实体。每次调用类名加括号(如Product())时,Python都会在内存中创建一个新的独立对象。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解剖类的结构:属性和方法详解
2.1 实例属性:对象独有的数据存储
在电商系统中,每个商品都有自己独特的属性值。实例属性就是存储这些对象特有数据的变量,通过self.属性名定义和访问。__init__方法是Python中特殊的初始化方法,在创建对象时自动调用:
python复制class Product:
def __init__(self, name, price):
self.name = name # 字符串类型
self.price = price # 数值类型
self.tags = [] # 列表类型
self._discount = 0 # 私有属性惯例以单下划线开头
属性可以随时动态添加,但好的实践是在__init__中明确定义所有可能的属性:
python复制shirt = Product("T恤", 99)
shirt.color = "白色" # 动态添加属性(不推荐)
2.2 实例方法:对象的行为能力
方法是定义在类中的函数,第一个参数总是self(指向当前对象实例)。通过方法,对象可以执行特定操作:
python复制class Product:
# ...其他代码...
def apply_discount(self, percent):
"""返回折扣后的价格"""
self._discount = percent
return self.price * (1 - percent/100)
def add_tag(self, tag):
"""添加商品标签"""
if tag not in self.tags:
self.tags.append(tag)
def display_info(self):
"""显示商品完整信息"""
info = f"{self.name} 原价:{self.price}"
if self._discount:
info += f" 折后价:{self.apply_discount(self._discount)}"
print(info)
方法调用时不需要传递self参数,Python会自动处理:
python复制bag = Product("背包", 299)
bag.apply_discount(20) # 自动传入bag作为self
bag.display_info() # 输出:背包 原价:299 折后价:239.2
2.3 类属性与静态方法:跨实例共享的元素
有时我们需要在所有对象间共享数据或功能。类属性直接定义在类中(不在方法内),而静态方法使用@staticmethod装饰器,不接收self参数:
python复制class Product:
tax_rate = 0.13 # 类属性-所有商品税率相同
@staticmethod
def validate_price(price):
"""静态方法-验证价格是否有效"""
return isinstance(price, (int, float)) and price > 0
def __init__(self, name, price):
if not self.validate_price(price): # 调用静态方法
raise ValueError("无效价格")
self.name = name
self.price = price
def price_with_tax(self):
"""计算含税价格"""
return self.price * (1 + Product.tax_rate) # 访问类属性
使用场景:
- 类属性:适用于所有实例相同的配置或常量
- 静态方法:与类相关但不需要访问实例数据的工具函数
3. 面向对象三大特性深度解析
3.1 封装:数据保护与接口设计
良好的封装就像电器外壳——隐藏内部复杂结构,只暴露必要的操作按钮。在Python中,我们通过命名约定实现封装:
python复制class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner # 公开属性
self._balance = balance # 受保护属性(约定)
self.__transaction_log = [] # 名称修饰(伪私有)
def deposit(self, amount):
"""存款"""
if amount > 0:
self._balance += amount
self.__update_log(f"存入{amount}")
return self._balance
def __update_log(self, message): # 私有方法
"""内部记录交易日志"""
self.__transaction_log.append(message)
def get_balance(self):
"""获取余额(控制访问)"""
return self._balance
实际开发经验:虽然Python没有真正的私有机制,但单下划线前缀向其他开发者表明"这是内部实现细节,请勿直接访问"。双下划线前缀会导致名称修饰(如_BankAccount__transaction_log),主要用于避免子类属性命名冲突。
3.2 继承:代码复用与层次化设计
继承让我们可以基于现有类创建新类,保留父类功能的同时添加或修改特定行为。假设我们要扩展电商系统支持数字商品:
python复制class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def display(self):
print(f"{self.name} - ${self.price}")
class DigitalProduct(Product): # 继承Product类
def __init__(self, name, price, file_size):
super().__init__(name, price) # 调用父类初始化
self.file_size = file_size # 新增属性
def display(self): # 方法重写
print(f"{self.name} - ${self.price} [{self.file_size}MB]")
# 使用示例
ebook = DigitalProduct("Python电子书", 39, 25)
ebook.display() # 输出:Python电子书 - $39 [25MB]
多重继承时方法解析顺序(MRO)很重要,Python使用C3算法确定搜索顺序:
python复制class A:
def test(self):
print("A")
class B(A):
def test(self):
print("B")
super().test()
class C(A):
def test(self):
print("C")
super().test()
class D(B, C):
pass
d = D()
d.test()
# 输出:
# B
# C
# A
3.3 多态:接口统一与灵活扩展
多态允许不同类对象对同一消息做出不同响应。在电商系统中,各种支付方式可以统一处理:
python复制class PaymentMethod:
def pay(self, amount):
raise NotImplementedError
class CreditCard(PaymentMethod):
def pay(self, amount):
print(f"信用卡支付{amount}元")
class Alipay(PaymentMethod):
def pay(self, amount):
print(f"支付宝支付{amount}元")
def process_payment(method, amount):
method.pay(amount) # 多态调用
# 使用示例
payment_methods = [CreditCard(), Alipay()]
for method in payment_methods:
process_payment(method, 100)
鸭子类型(Duck Typing)是Python多态的典型体现:"如果它走起来像鸭子,叫起来像鸭子,那么它就是鸭子"。我们不需要严格继承关系,只要对象实现了所需方法即可:
python复制class WeChatPay: # 没有继承PaymentMethod
def pay(self, amount):
print(f"微信支付{amount}元")
process_payment(WeChatPay(), 100) # 依然可以工作
4. Python类的高级特性与应用技巧
4.1 特殊方法:让类行为像内置类型
通过实现特殊方法(双下划线方法),我们可以自定义类的各种行为。比如让商品对象支持加法运算(合并商品包):
python复制class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def __add__(self, other):
"""重载+运算符"""
new_name = f"{self.name}+{other.name}"
new_price = self.price + other.price
return Product(new_name, new_price)
def __str__(self):
"""定义打印格式"""
return f"Product({self.name}, ${self.price})"
def __len__(self):
"""定义len()行为-返回名称长度"""
return len(self.name)
# 使用示例
p1 = Product("鼠标", 50)
p2 = Product("键盘", 80)
combo = p1 + p2 # 调用__add__
print(combo) # 调用__str__ 输出:Product(鼠标+键盘, $130)
print(len(p1)) # 调用__len__ 输出:2
常用特殊方法包括:
- init:构造器
- str:字符串表示
- eq:定义==行为
- getitem:实现下标访问
- call:使实例可像函数一样调用
4.2 属性装饰器:精细化控制属性访问
@property装饰器让我们可以像访问属性一样调用方法,同时添加访问控制逻辑:
python复制class Temperature:
def __init__(self, celsius):
self.celsius = celsius
@property
def celsius(self):
"""获取摄氏温度"""
return self._celsius
@celsius.setter
def celsius(self, value):
"""设置摄氏温度并验证"""
if not isinstance(value, (int, float)):
raise ValueError("温度必须是数字")
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
temp.celsius = -300 # 抛出ValueError
4.3 类装饰器与元类:高级定制工具
类装饰器可以修改或增强类定义,而元类(metaclass)则控制类本身的创建过程:
python复制# 类装饰器示例-自动添加创建时间
def add_timestamp(cls):
cls.created_at = datetime.now()
return cls
@add_timestamp
class MyClass:
pass
print(MyClass.created_at) # 输出创建时间
# 元类示例-强制类必须有文档字符串
class DocumentedMeta(type):
def __new__(cls, name, bases, namespace):
if not namespace.get('__doc__'):
raise TypeError(f"类 {name} 必须包含文档字符串")
return super().__new__(cls, name, bases, namespace)
class Product(metaclass=DocumentedMeta):
"""商品基类"""
pass
class BadClass(metaclass=DocumentedMeta): # 会抛出TypeError
pass
实际项目中,这些高级特性常用于:
- ORM框架(如Django模型)
- API接口验证
- 自动化测试框架
- 插件系统实现
4.4 抽象基类:定义接口规范
abc模块提供抽象基类支持,用于定义必须实现的接口:
python复制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() # 报错:不能实例化抽象类
c = Circle(5) # 必须实现所有抽象方法
抽象基类常用于:
- 框架设计时规定必须实现的方法
- 大型项目中明确接口约定
- 配合register方法实现接口注册
5. 实战:设计一个电商系统商品模块
结合以上知识,我们来设计一个完整的商品系统,包含以下功能:
- 基础商品分类
- 价格计算策略
- 库存管理
- 折扣活动
5.1 基础类结构设计
python复制from abc import ABC, abstractmethod
from datetime import datetime, timedelta
from typing import List
class Product(ABC):
"""商品抽象基类"""
def __init__(self, name: str, base_price: float):
self.name = name
self._base_price = base_price
self._inventory = 0
self.created_at = datetime.now()
@property
def base_price(self) -> float:
return self._base_price
@base_price.setter
def base_price(self, value: float):
if value <= 0:
raise ValueError("价格必须大于0")
self._base_price = value
@property
def inventory(self) -> int:
return self._inventory
def add_inventory(self, amount: int):
"""增加库存"""
if amount <= 0:
raise ValueError("增加数量必须为正")
self._inventory += amount
def reduce_inventory(self, amount: int) -> bool:
"""减少库存,成功返回True"""
if amount <= 0:
raise ValueError("减少数量必须为正")
if self._inventory < amount:
return False
self._inventory -= amount
return True
@abstractmethod
def calculate_price(self) -> float:
"""计算实际售价(子类必须实现)"""
pass
def __str__(self):
return f"{self.name} - 库存:{self.inventory} 基价:{self.base_price}"
class PhysicalProduct(Product):
"""实体商品"""
def __init__(self, name: str, base_price: float, weight: float):
super().__init__(name, base_price)
self.weight = weight # 重量(kg)
def calculate_price(self) -> float:
"""实体商品价格=基价+运费"""
shipping_cost = max(10, self.weight * 5) # 运费计算
return self.base_price + shipping_cost
class DigitalProduct(Product):
"""数字商品"""
def calculate_price(self) -> float:
"""数字商品无运费"""
return self.base_price
5.2 实现价格策略模式
使用策略模式灵活支持各种折扣活动:
python复制class PricingStrategy(ABC):
"""价格策略接口"""
@abstractmethod
def apply_discount(self, price: float) -> float:
pass
class PercentageDiscount(PricingStrategy):
"""百分比折扣"""
def __init__(self, percent: float):
self.percent = percent
def apply_discount(self, price: float) -> float:
return price * (1 - self.percent / 100)
class FixedDiscount(PricingStrategy):
"""固定金额折扣"""
def __init__(self, amount: float):
self.amount = amount
def apply_discount(self, price: float) -> float:
return max(0, price - self.amount)
class DiscountedProduct(Product):
"""支持折扣的商品"""
def __init__(self, product: Product, strategy: PricingStrategy):
self._product = product
self._strategy = strategy
def calculate_price(self) -> float:
base_price = self._product.calculate_price()
return self._strategy.apply_discount(base_price)
def __getattr__(self, name):
"""委托其他属性访问到原始产品"""
return getattr(self._product, name)
# 使用示例
laptop = PhysicalProduct("笔记本电脑", 5999, 2.5)
laptop.add_inventory(10)
# 创建八折策略
discount_strategy = PercentageDiscount(20)
discounted_laptop = DiscountedProduct(laptop, discount_strategy)
print(f"原价: {laptop.calculate_price()}") # 6009 (5999+10运费)
print(f"折后价: {discounted_laptop.calculate_price()}") # 4807.2
5.3 实现商品组合与装饰器模式
支持商品捆绑销售和附加服务:
python复制class ProductBundle(Product):
"""商品组合包"""
def __init__(self, name: str, products: List[Product]):
total_price = sum(p.calculate_price() for p in products)
super().__init__(name, total_price)
self.products = products
def calculate_price(self) -> float:
"""组合包价格=所有商品价格总和*0.9"""
return super().calculate_price() * 0.9
def add_inventory(self, amount: int):
"""为每个商品增加库存"""
for product in self.products:
product.add_inventory(amount)
def reduce_inventory(self, amount: int) -> bool:
"""检查所有商品库存是否足够"""
if all(p.inventory >= amount for p in self.products):
for product in self.products:
product.reduce_inventory(amount)
return True
return False
class ProductWithWarranty(Product):
"""带保修服务的商品"""
def __init__(self, product: Product, years: int):
super().__init__(f"{product.name}({years}年保修)", product.base_price)
self._product = product
self.warranty_years = years
def calculate_price(self) -> float:
"""保修价格=商品价格+保修费用"""
return self._product.calculate_price() + self.warranty_years * 100
# 使用示例
mouse = PhysicalProduct("无线鼠标", 199, 0.2)
keyboard = PhysicalProduct("机械键盘", 499, 1.0)
# 创建外设套装
peripheral_kit = ProductBundle("键鼠套装", [mouse, keyboard])
peripheral_kit.add_inventory(5)
# 添加2年保修
warranty_kit = ProductWithWarranty(peripheral_kit, 2)
print(f"套装原价: {peripheral_kit.calculate_price()}") # (199+499)*0.9=628.2
print(f"带保修价格: {warranty_kit.calculate_price()}") # 628.2+200=828.2
5.4 实现库存管理与订单处理
完整的库存管理和订单处理系统:
python复制class Inventory:
"""库存管理系统"""
def __init__(self):
self.products = {}
def add_product(self, product: Product, initial_stock: int = 0):
"""添加商品到库存"""
if product.name in self.products:
raise ValueError("商品已存在")
self.products[product.name] = product
if initial_stock > 0:
product.add_inventory(initial_stock)
def check_stock(self, product_name: str) -> int:
"""检查库存"""
product = self.products.get(product_name)
if not product:
raise ValueError("商品不存在")
return product.inventory
def bulk_purchase(self, items: dict) -> bool:
"""批量购买,成功返回True"""
# 首先检查所有商品库存是否足够
for product_name, amount in items.items():
if product_name not in self.products:
raise ValueError(f"商品 {product_name} 不存在")
if self.products[product_name].inventory < amount:
return False
# 所有库存足够,执行扣减
for product_name, amount in items.items():
self.products[product_name].reduce_inventory(amount)
return True
class Order:
"""订单类"""
def __init__(self, order_id: str, inventory: Inventory):
self.order_id = order_id
self.inventory = inventory
self.items = {} # {商品名: 数量}
self.created_at = datetime.now()
self.total = 0
def add_item(self, product_name: str, quantity: int = 1):
"""添加商品到订单"""
if product_name in self.items:
self.items[product_name] += quantity
else:
self.items[product_name] = quantity
def calculate_total(self, pricing_strategy: PricingStrategy = None) -> float:
"""计算订单总价"""
total = 0
for product_name, quantity in self.items.items():
product = self.inventory.products[product_name]
total += product.calculate_price() * quantity
if pricing_strategy:
total = pricing_strategy.apply_discount(total)
self.total = total
return total
def checkout(self) -> bool:
"""结账,成功返回True"""
if self.inventory.bulk_purchase(self.items):
print(f"订单 {self.order_id} 完成,总价: {self.total}")
return True
print(f"订单 {self.order_id} 库存不足")
return False
# 完整使用示例
# 初始化库存
inventory = Inventory()
inventory.add_product(PhysicalProduct("iPhone", 7999, 0.3), 10)
inventory.add_product(DigitalProduct("电子书", 39), 1000)
# 创建订单
order = Order("20230001", inventory)
order.add_item("iPhone", 2)
order.add_item("电子书", 3)
# 应用会员折扣
vip_discount = PercentageDiscount(10)
total = order.calculate_total(vip_discount)
print(f"折后总价: {total}")
# 结账
order.checkout()
