Python 面向对象编程

1 阅读18分钟

Python 面向对象编程

目录


面向对象基础

什么是面向对象?

面向对象编程(OOP)是一种编程范式,它将数据和操作数据的方法组织成"对象"。

核心概念

  • 类(Class):对象的蓝图或模板
  • 对象(Object):类的实例
  • 属性(Attribute):对象的数据
  • 方法(Method):对象的行为
# 面向过程 vs 面向对象

# ❌ 面向过程
def create_dog(name, age):
    return {"name": name, "age": age}

def dog_bark(dog):
    print(f"{dog['name']} says: Woof!")

my_dog = create_dog("Buddy", 3)
dog_bark(my_dog)

# ✅ 面向对象
class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def bark(self):
        print(f"{self.name} says: Woof!")

my_dog = Dog("Buddy", 3)
my_dog.bark()

面向对象的四大特性

  1. 封装:隐藏内部实现细节
  2. 继承:代码复用和扩展
  3. 多态:同一接口,不同实现
  4. 抽象:提取共同特征

类和对象

定义类

# 基本类定义
class Person:
    """人类"""
    pass

# 创建对象
person1 = Person()
person2 = Person()

print(type(person1))  # <class '__main__.Person'>
print(person1 is person2)  # False(不同的对象)

添加属性和方法

class Person:
    """人类"""

    def greet(self):
        """打招呼"""
        print("Hello!")

# 使用
person = Person()
person.greet()  # Hello!

构造函数

__init__ 方法

class Person:
    def __init__(self, name, age):
        """构造函数,在创建对象时自动调用"""
        self.name = name  # 实例属性
        self.age = age
        print(f"创建了 {self.name}")

# 创建对象时传入参数
person = Person("张三", 25)
print(person.name)  # 张三
print(person.age)   # 25

默认参数

class Person:
    def __init__(self, name, age=0, city="未知"):
        self.name = name
        self.age = age
        self.city = city

person1 = Person("张三")
person2 = Person("李四", 25)
person3 = Person("王五", 30, "北京")

print(person1.city)  # 未知
print(person2.age)   # 25
print(person3.city)  # 北京

实例属性和方法

实例属性

class Student:
    def __init__(self, name, student_id):
        self.name = name          # 实例属性
        self.student_id = student_id
        self.grades = []          # 可变属性

# 每个对象有独立的属性
student1 = Student("张三", "001")
student2 = Student("李四", "002")

student1.grades.append(90)
student2.grades.append(85)

print(student1.grades)  # [90]
print(student2.grades)  # [85]

实例方法

class Student:
    def __init__(self, name, student_id):
        self.name = name
        self.student_id = student_id
        self.grades = []

    def add_grade(self, grade):
        """添加成绩"""
        if 0 <= grade <= 100:
            self.grades.append(grade)
            print(f"添加成绩: {grade}")
        else:
            print("成绩必须在0-100之间")

    def get_average(self):
        """计算平均分"""
        if not self.grades:
            return 0
        return sum(self.grades) / len(self.grades)

    def display_info(self):
        """显示学生信息"""
        avg = self.get_average()
        print(f"姓名: {self.name}")
        print(f"学号: {self.student_id}")
        print(f"成绩: {self.grades}")
        print(f"平均分: {avg:.2f}")

# 使用
student = Student("张三", "001")
student.add_grade(90)
student.add_grade(85)
student.add_grade(92)
student.display_info()

self 参数

class Dog:
    def __init__(self, name):
        self.name = name

    def bark(self):
        # self 指向当前对象实例
        print(f"{self.name} says: Woof!")

    def introduce(self):
        # 可以调用其他方法
        self.bark()
        print(f"I am {self.name}")

dog = Dog("Buddy")
dog.introduce()
# Buddy says: Woof!
# I am Buddy

类属性和类方法

类属性

class Employee:
    # 类属性(所有实例共享)
    company = "ABC公司"
    employee_count = 0

    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        # 每创建一个员工,计数+1
        Employee.employee_count += 1

emp1 = Employee("张三", 8000)
emp2 = Employee("李四", 9000)

# 访问类属性
print(Employee.company)           # ABC公司
print(Employee.employee_count)    # 2
print(emp1.company)               # ABC公司(也可以通过实例访问)
print(emp2.employee_count)        # 2

类方法

class Employee:
    company = "ABC公司"

    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

    @classmethod
    def change_company(cls, new_company):
        """类方法:修改公司名称"""
        cls.company = new_company
        print(f"公司更名为: {new_company}")

    @classmethod
    def from_string(cls, emp_str):
        """类方法:从字符串创建对象"""
        name, salary = emp_str.split("-")
        return cls(name, int(salary))

# 使用类方法
Employee.change_company("XYZ公司")

# 工厂方法
emp = Employee.from_string("王五-10000")
print(emp.name)    # 王五
print(emp.salary)  # 10000

静态方法

class MathUtils:
    @staticmethod
    def add(a, b):
        """静态方法:不需要访问类或实例"""
        return a + b

    @staticmethod
    def is_even(number):
        return number % 2 == 0

    @staticmethod
    def validate_email(email):
        """验证邮箱格式"""
        return "@" in email and "." in email

# 使用静态方法(不需要创建实例)
print(MathUtils.add(5, 3))           # 8
print(MathUtils.is_even(10))         # True
print(MathUtils.validate_email("test@example.com"))  # True

三种方法对比

class MyClass:
    class_var = "类变量"

    def __init__(self, value):
        self.instance_var = value

    def instance_method(self):
        """实例方法:可以访问实例和类"""
        print(f"实例变量: {self.instance_var}")
        print(f"类变量: {MyClass.class_var}")

    @classmethod
    def class_method(cls):
        """类方法:只能访问类"""
        print(f"类变量: {cls.class_var}")
        # print(self.instance_var)  # ❌ 错误

    @staticmethod
    def static_method():
        """静态方法:不能访问实例或类"""
        print("静态方法")
        # print(self.instance_var)  # ❌ 错误
        # print(MyClass.class_var)  # 可以但不推荐

obj = MyClass("实例值")
obj.instance_method()
MyClass.class_method()
MyClass.static_method()

封装

访问控制

Python 没有严格的访问控制,但有以下约定:

  • public:公开(默认)
  • _protected:受保护(约定,不强制)
  • __private:私有(名称修饰)
class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner           # 公开
        self._balance = balance      # 受保护(约定不要直接访问)
        self.__pin = "1234"          # 私有(名称修饰)

    def deposit(self, amount):
        if amount > 0:
            self._balance += amount
            print(f"存入: {amount}, 余额: {self._balance}")

    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)
account.withdraw(200)
print(account.get_balance())  # 1300

# ❌ 不推荐直接访问
# print(account._balance)

# ❌ 无法直接访问私有属性
# print(account.__pin)  # AttributeError

# 实际上可以通过名称修饰访问(但不应该这样做)
print(account._BankAccount__pin)  # 1234(不推荐)

Getter 和 Setter

class Temperature:
    def __init__(self, celsius=0):
        self._celsius = celsius

    # Getter
    def get_celsius(self):
        return self._celsius

    # Setter
    def set_celsius(self, value):
        if value < -273.15:
            raise ValueError("温度不能低于绝对零度")
        self._celsius = value

    def get_fahrenheit(self):
        return self._celsius * 9/5 + 32

temp = Temperature(25)
print(temp.get_celsius())     # 25
print(temp.get_fahrenheit())  # 77.0

temp.set_celsius(30)
print(temp.get_celsius())     # 30

继承

基本继承

# 父类(基类)
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def speak(self):
        print(f"{self.name} makes a sound")

    def describe(self):
        print(f"{self.name}, {self.age}岁")

# 子类(派生类)
class Dog(Animal):
    def speak(self):
        print(f"{self.name} says: Woof!")

class Cat(Animal):
    def speak(self):
        print(f"{self.name} says: Meow!")

# 使用
dog = Dog("Buddy", 3)
cat = Cat("Kitty", 2)

dog.describe()  # Buddy, 3岁
dog.speak()     # Buddy says: Woof!

cat.describe()  # Kitty, 2岁
cat.speak()     # Kitty says: Meow!

super() 函数

class Bird(Animal):
    def __init__(self, name, age, can_fly=True):
        # 调用父类的构造函数
        super().__init__(name, age)
        self.can_fly = can_fly

    def describe(self):
        # 调用父类的方法
        super().describe()
        fly_status = "会飞" if self.can_fly else "不会飞"
        print(f"飞行能力: {fly_status}")

bird = Bird("鹦鹉", 5, True)
bird.describe()
# 鹦鹉, 5岁
# 飞行能力: 会飞

多层继承

class GrandParent:
    def __init__(self):
        self.family_name = "张"

class Parent(GrandParent):
    def __init__(self):
        super().__init__()
        self.generation = "父母辈"

class Child(Parent):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def introduce(self):
        print(f"我叫{self.name},姓{self.family_name},是{self.generation}")

child = Child("小明")
child.introduce()  # 我叫小明,姓张,是父母辈

多重继承

class Flyable:
    def fly(self):
        print("我在飞")

class Swimmable:
    def swim(self):
        print("我在游泳")

class Duck(Flyable, Swimmable):
    def __init__(self, name):
        self.name = name

    def introduce(self):
        print(f"我是{self.name}")

duck = Duck("唐老鸭")
duck.introduce()  # 我是唐老鸭
duck.fly()        # 我在飞
duck.swim()       # 我在游泳

MRO(方法解析顺序)

class A:
    def method(self):
        print("A.method")

class B(A):
    def method(self):
        print("B.method")

class C(A):
    def method(self):
        print("C.method")

class D(B, C):
    pass

d = D()
d.method()  # B.method

# 查看MRO
print(D.mro())
# [<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>]

isinstance 和 issubclass

class Animal:
    pass

class Dog(Animal):
    pass

class Cat(Animal):
    pass

dog = Dog()

# 检查实例类型
print(isinstance(dog, Dog))     # True
print(isinstance(dog, Animal))  # True
print(isinstance(dog, Cat))     # False

# 检查类的继承关系
print(issubclass(Dog, Animal))  # True
print(issubclass(Cat, Animal))  # True
print(issubclass(Dog, Cat))     # False

多态

方法重写

class Shape:
    def area(self):
        raise NotImplementedError("子类必须实现此方法")

    def describe(self):
        print(f"面积: {self.area()}")

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        import math
        return math.pi * self.radius ** 2

# 多态:同样的接口,不同的行为
shapes = [Rectangle(5, 10), Circle(7)]

for shape in shapes:
    shape.describe()
# 面积: 50
# 面积: 153.938...

鸭子类型

# Python 的鸭子类型:"如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子"

class Duck:
    def quack(self):
        print("Quack!")

class Person:
    def quack(self):
        print("我在模仿鸭子叫")

def make_it_quack(thing):
    # 不关心类型,只关心是否有 quack 方法
    thing.quack()

make_it_quack(Duck())    # Quack!
make_it_quack(Person())  # 我在模仿鸭子叫

魔术方法

魔术方法(特殊方法)以双下划线开头和结尾,用于自定义类的行为。

字符串表示

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        """用户友好的字符串表示"""
        return f"{self.name}({self.age}岁)"

    def __repr__(self):
        """开发者友好的字符串表示"""
        return f"Person('{self.name}', {self.age})"

person = Person("张三", 25)
print(str(person))   # 张三(25岁)
print(repr(person))  # Person('张三', 25)

比较运算符

class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def __eq__(self, other):
        """=="""
        if isinstance(other, Student):
            return self.score == other.score
        return NotImplemented

    def __lt__(self, other):
        """<"""
        if isinstance(other, Student):
            return self.score < other.score
        return NotImplemented

    def __le__(self, other):
        """<="""
        if isinstance(other, Student):
            return self.score <= other.score
        return NotImplemented

    def __gt__(self, other):
        """>"""
        if isinstance(other, Student):
            return self.score > other.score
        return NotImplemented

    def __ge__(self, other):
        """>="""
        if isinstance(other, Student):
            return self.score >= other.score
        return NotImplemented

s1 = Student("张三", 90)
s2 = Student("李四", 85)

print(s1 > s2)   # True
print(s1 == s2)  # False
print(s1 >= s2)  # True

算术运算符

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        """+"""
        if isinstance(other, Vector):
            return Vector(self.x + other.x, self.y + other.y)
        return NotImplemented

    def __sub__(self, other):
        """-"""
        if isinstance(other, Vector):
            return Vector(self.x - other.x, self.y - other.y)
        return NotImplemented

    def __mul__(self, scalar):
        """*"""
        if isinstance(scalar, (int, float)):
            return Vector(self.x * scalar, self.y * scalar)
        return NotImplemented

    def __str__(self):
        return f"Vector({self.x}, {self.y})"

v1 = Vector(1, 2)
v2 = Vector(3, 4)

print(v1 + v2)      # Vector(4, 6)
print(v1 - v2)      # Vector(-2, -2)
print(v1 * 3)       # Vector(3, 6)

容器相关方法

class MyList:
    def __init__(self, items=None):
        self.items = items or []

    def __len__(self):
        """len()"""
        return len(self.items)

    def __getitem__(self, index):
        """索引访问"""
        return self.items[index]

    def __setitem__(self, index, value):
        """索引赋值"""
        self.items[index] = value

    def __delitem__(self, index):
        """删除元素"""
        del self.items[index]

    def __contains__(self, item):
        """in 操作符"""
        return item in self.items

    def __iter__(self):
        """迭代"""
        return iter(self.items)

    def __str__(self):
        return str(self.items)

my_list = MyList([1, 2, 3, 4, 5])
print(len(my_list))      # 5
print(my_list[0])        # 1
print(3 in my_list)      # True

for item in my_list:
    print(item, end=" ")  # 1 2 3 4 5

常用魔术方法总结

class Example:
    # 初始化和销毁
    def __init__(self):      # 构造
        pass
    def __del__(self):       # 析构
        pass

    # 字符串表示
    def __str__(self):       # str()
        pass
    def __repr__(self):      # repr()
        pass

    # 比较
    def __eq__(self, other): # ==
        pass
    def __lt__(self, other): # <
        pass

    # 算术
    def __add__(self, other): # +
        pass
    def __sub__(self, other): # -
        pass

    # 容器
    def __len__(self):        # len()
        pass
    def __getitem__(self, key): # obj[key]
        pass
    def __setitem__(self, key, value): # obj[key] = value
        pass
    def __contains__(self, item): # in
        pass
    def __iter__(self):       # iter()
        pass

    # 调用
    def __call__(self, *args): # obj()
        pass

    # 上下文管理器
    def __enter__(self):      # with语句进入
        pass
    def __exit__(self, *args): # with语句退出
        pass

属性装饰器

@property

class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        """getter"""
        return self._radius

    @radius.setter
    def radius(self, value):
        """setter"""
        if value < 0:
            raise ValueError("半径不能为负数")
        self._radius = value

    @property
    def area(self):
        """只读属性"""
        import math
        return math.pi * self._radius ** 2

circle = Circle(5)
print(circle.radius)  # 5(调用 getter)
print(circle.area)    # 78.54...(只读)

circle.radius = 10    # 调用 setter
print(circle.radius)  # 10

# circle.area = 100   # ❌ AttributeError: 只读

计算属性

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.height

    @property
    def perimeter(self):
        return 2 * (self.width + self.height)

    @property
    def is_square(self):
        return self.width == self.height

rect = Rectangle(5, 10)
print(rect.area)        # 50
print(rect.perimeter)   # 30
print(rect.is_square)   # False

组合与聚合

组合(强关系)

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

    def start(self):
        print(f"引擎启动 ({self.horsepower}马力)")

class Car:
    def __init__(self, brand, engine):
        self.brand = brand
        self.engine = engine  # 组合:Car 拥有 Engine

    def start(self):
        print(f"{self.brand} 汽车启动")
        self.engine.start()

# Engine 是 Car 的一部分,生命周期绑定
engine = Engine(200)
car = Car("丰田", engine)
car.start()
# 丰田 汽车启动
# 引擎启动 (200马力)

聚合(弱关系)

class Teacher:
    def __init__(self, name):
        self.name = name

class Department:
    def __init__(self, name):
        self.name = name
        self.teachers = []  # 聚合:Department 包含 Teachers

    def add_teacher(self, teacher):
        self.teachers.append(teacher)

    def list_teachers(self):
        print(f"{self.name} 的教师:")
        for teacher in self.teachers:
            print(f"  - {teacher.name}")

# Teacher 可以独立于 Department 存在
teacher1 = Teacher("张老师")
teacher2 = Teacher("李老师")

dept = Department("计算机系")
dept.add_teacher(teacher1)
dept.add_teacher(teacher2)
dept.list_teachers()

抽象基类

ABC 模块

from abc import ABC, abstractmethod

class Shape(ABC):
    """抽象基类"""

    @abstractmethod
    def area(self):
        """计算面积(必须由子类实现)"""
        pass

    @abstractmethod
    def perimeter(self):
        """计算周长(必须由子类实现)"""
        pass

    def describe(self):
        """具体方法(可选实现)"""
        print(f"面积: {self.area()}, 周长: {self.perimeter()}")

# ❌ 不能实例化抽象类
# shape = Shape()  # TypeError

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

    def perimeter(self):
        return 2 * (self.width + self.height)

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        import math
        return math.pi * self.radius ** 2

    def perimeter(self):
        import math
        return 2 * math.pi * self.radius

# ✅ 可以实例化具体子类
rect = Rectangle(5, 10)
rect.describe()

circle = Circle(7)
circle.describe()

综合实战

实战1: 银行账户系统

from abc import ABC, abstractmethod
from datetime import datetime

class Transaction:
    """交易记录"""
    def __init__(self, transaction_type, amount, description=""):
        self.type = transaction_type  # "deposit" 或 "withdrawal"
        self.amount = amount
        self.description = description
        self.timestamp = datetime.now()

    def __str__(self):
        type_cn = "存款" if self.type == "deposit" else "取款"
        return f"[{self.timestamp}] {type_cn}: ¥{self.amount:.2f} {self.description}"

class BankAccount(ABC):
    """银行账户抽象基类"""

    def __init__(self, owner, account_number, initial_balance=0):
        self.owner = owner
        self.account_number = account_number
        self._balance = initial_balance
        self.transactions = []

        if initial_balance > 0:
            self.transactions.append(
                Transaction("deposit", initial_balance, "初始存款")
            )

    @property
    def balance(self):
        return self._balance

    def deposit(self, amount):
        """存款"""
        if amount <= 0:
            raise ValueError("存款金额必须大于0")

        self._balance += amount
        transaction = Transaction("deposit", amount)
        self.transactions.append(transaction)
        print(f"✓ 存款成功: ¥{amount:.2f}, 余额: ¥{self._balance:.2f}")

    def withdraw(self, amount):
        """取款"""
        if amount <= 0:
            raise ValueError("取款金额必须大于0")

        if amount > self._balance:
            raise ValueError("余额不足")

        self._balance -= amount
        transaction = Transaction("withdrawal", amount)
        self.transactions.append(transaction)
        print(f"✓ 取款成功: ¥{amount:.2f}, 余额: ¥{self._balance:.2f}")

    def get_statement(self):
        """获取账单"""
        print(f"\n{'='*50}")
        print(f"账户持有人: {self.owner}")
        print(f"账号: {self.account_number}")
        print(f"当前余额: ¥{self._balance:.2f}")
        print(f"{'='*50}")
        print("交易记录:")
        for transaction in self.transactions[-10:]:  # 最近10条
            print(f"  {transaction}")
        print(f"{'='*50}\n")

    @abstractmethod
    def calculate_interest(self):
        """计算利息(由子类实现)"""
        pass

class SavingsAccount(BankAccount):
    """储蓄账户"""

    def __init__(self, owner, account_number, interest_rate=0.03, initial_balance=0):
        super().__init__(owner, account_number, initial_balance)
        self.interest_rate = interest_rate

    def calculate_interest(self):
        """计算年利息"""
        interest = self._balance * self.interest_rate
        print(f"年利息率: {self.interest_rate*100}%")
        print(f"年利息: ¥{interest:.2f}")
        return interest

class CheckingAccount(BankAccount):
    """支票账户"""

    def __init__(self, owner, account_number, overdraft_limit=0, initial_balance=0):
        super().__init__(owner, account_number, initial_balance)
        self.overdraft_limit = overdraft_limit

    def withdraw(self, amount):
        """支持透支"""
        if amount <= 0:
            raise ValueError("取款金额必须大于0")

        if amount > self._balance + self.overdraft_limit:
            raise ValueError("超过透支额度")

        self._balance -= amount
        transaction = Transaction("withdrawal", amount)
        self.transactions.append(transaction)
        print(f"✓ 取款成功: ¥{amount:.2f}, 余额: ¥{self._balance:.2f}")

    def calculate_interest(self):
        """支票账户通常无利息"""
        print("支票账户无利息")
        return 0

# 使用示例
savings = SavingsAccount("张三", "SAV001", interest_rate=0.03, initial_balance=10000)
savings.deposit(5000)
savings.withdraw(2000)
savings.calculate_interest()
savings.get_statement()

checking = CheckingAccount("李四", "CHK001", overdraft_limit=5000, initial_balance=1000)
checking.withdraw(3000)  # 透支
checking.get_statement()

实战2: RPG 游戏角色系统

from abc import ABC, abstractmethod
import random

class Item:
    """物品"""
    def __init__(self, name, value):
        self.name = name
        self.value = value

    def __str__(self):
        return f"{self.name} (价值: {self.value})"

class Weapon(Item):
    """武器"""
    def __init__(self, name, value, damage):
        super().__init__(name, value)
        self.damage = damage

    def __str__(self):
        return f"⚔️ {self.name} (攻击力: {self.damage}, 价值: {self.value})"

class Armor(Item):
    """护甲"""
    def __init__(self, name, value, defense):
        super().__init__(name, value)
        self.defense = defense

    def __str__(self):
        return f"🛡️ {self.name} (防御力: {self.defense}, 价值: {self.value})"

class Character(ABC):
    """角色抽象基类"""

    def __init__(self, name, level=1):
        self.name = name
        self.level = level
        self.max_hp = 100 + (level - 1) * 20
        self.hp = self.max_hp
        self.base_attack = 10 + (level - 1) * 5
        self.base_defense = 5 + (level - 1) * 3
        self.experience = 0
        self.inventory = []
        self.equipped_weapon = None
        self.equipped_armor = None

    @property
    def attack(self):
        """总攻击力"""
        weapon_damage = self.equipped_weapon.damage if self.equipped_weapon else 0
        return self.base_attack + weapon_damage

    @property
    def defense(self):
        """总防御力"""
        armor_defense = self.equipped_armor.defense if self.equipped_armor else 0
        return self.base_defense + armor_defense

    def take_damage(self, damage):
        """受到伤害"""
        actual_damage = max(1, damage - self.defense)
        self.hp -= actual_damage
        print(f"{self.name} 受到 {actual_damage} 点伤害")

        if self.hp <= 0:
            self.hp = 0
            print(f"{self.name} 被击败了!")
            return True
        return False

    def heal(self, amount):
        """治疗"""
        old_hp = self.hp
        self.hp = min(self.max_hp, self.hp + amount)
        healed = self.hp - old_hp
        print(f"{self.name} 恢复了 {healed} 点生命值")

    def add_item(self, item):
        """添加物品"""
        self.inventory.append(item)
        print(f"{self.name} 获得了 {item}")

    def equip_weapon(self, weapon):
        """装备武器"""
        if weapon in self.inventory:
            self.equipped_weapon = weapon
            print(f"{self.name} 装备了 {weapon.name}")
        else:
            print(f"{self.name} 没有 {weapon.name}")

    def equip_armor(self, armor):
        """装备护甲"""
        if armor in self.inventory:
            self.equipped_armor = armor
            print(f"{self.name} 装备了 {armor.name}")
        else:
            print(f"{self.name} 没有 {armor.name}")

    def gain_experience(self, exp):
        """获得经验"""
        self.experience += exp
        print(f"{self.name} 获得 {exp} 点经验")

        # 简单升级逻辑
        exp_needed = self.level * 100
        if self.experience >= exp_needed:
            self.level_up()

    def level_up(self):
        """升级"""
        self.level += 1
        self.max_hp += 20
        self.hp = self.max_hp
        self.base_attack += 5
        self.base_defense += 3
        print(f"🎉 {self.name} 升级到 {self.level} 级!")

    def show_status(self):
        """显示状态"""
        print(f"\n{'='*40}")
        print(f"👤 {self.name} (Lv.{self.level})")
        print(f"❤️  HP: {self.hp}/{self.max_hp}")
        print(f"⚔️  攻击: {self.attack}")
        print(f"🛡️  防御: {self.defense}")
        print(f"⭐ 经验: {self.experience}")

        if self.equipped_weapon:
            print(f"武器: {self.equipped_weapon.name}")
        if self.equipped_armor:
            print(f"护甲: {self.equipped_armor.name}")

        if self.inventory:
            print(f"背包: {[str(item) for item in self.inventory]}")
        print(f"{'='*40}\n")

    @abstractmethod
    def special_ability(self):
        """特殊技能(由子类实现)"""
        pass

class Warrior(Character):
    """战士"""

    def special_ability(self):
        """狂暴:大幅提升攻击力"""
        print(f"💥 {self.name} 使用狂暴!")
        old_attack = self.base_attack
        self.base_attack *= 2
        print(f"攻击力从 {old_attack} 提升到 {self.base_attack}")
        return "狂暴"

class Mage(Character):
    """法师"""

    def __init__(self, name, level=1):
        super().__init__(name, level)
        self.mana = 50 + (level - 1) * 10
        self.max_mana = self.mana

    def special_ability(self):
        """火球术:魔法攻击"""
        if self.mana >= 20:
            self.mana -= 20
            damage = self.attack * 1.5
            print(f"🔥 {self.name} 施放火球术!造成 {damage:.0f} 点伤害")
            return damage
        else:
            print(f"{self.name} 法力不足!")
            return 0

class Healer(Character):
    """治疗者"""

    def __init__(self, name, level=1):
        super().__init__(name, level)
        self.mana = 60 + (level - 1) * 15
        self.max_mana = self.mana

    def special_ability(self, target=None):
        """治疗术"""
        if self.mana >= 15:
            self.mana -= 15
            heal_amount = self.max_hp * 0.3
            if target:
                target.heal(heal_amount)
                print(f"✨ {self.name}{target.name} 施放治疗术")
            else:
                self.heal(heal_amount)
                print(f"✨ {self.name} 为自己施放治疗术")
            return heal_amount
        else:
            print(f"{self.name} 法力不足!")
            return 0

# 战斗系统
def battle(character1, character2):
    """回合制战斗"""
    print(f"\n⚔️  战斗开始: {character1.name} VS {character2.name}\n")

    round_num = 1
    while character1.hp > 0 and character2.hp > 0:
        print(f"--- 第 {round_num} 回合 ---")

        # 角色1行动
        damage = character1.attack
        defeated = character2.take_damage(damage)
        if defeated:
            character1.gain_experience(50)
            break

        # 角色2行动
        damage = character2.attack
        defeated = character1.take_damage(damage)
        if defeated:
            character2.gain_experience(50)
            break

        round_num += 1
        print()

    print("\n战斗结束\n")

# 使用示例
warrior = Warrior("亚瑟", level=5)
mage = Mage("梅林", level=5)

# 添加装备
sword = Weapon("圣剑", 500, 30)
staff = Weapon("法杖", 400, 20)
armor = Armor("铁甲", 300, 15)

warrior.add_item(sword)
warrior.add_item(armor)
mage.add_item(staff)

warrior.equip_weapon(sword)
warrior.equip_armor(armor)
mage.equip_weapon(staff)

warrior.show_status()
mage.show_status()

battle(warrior, mage)

实战3: 电商订单系统

from datetime import datetime
from enum import Enum

class OrderStatus(Enum):
    """订单状态枚举"""
    PENDING = "待支付"
    PAID = "已支付"
    SHIPPED = "已发货"
    DELIVERED = "已送达"
    CANCELLED = "已取消"

class Product:
    """商品"""

    def __init__(self, product_id, name, price, stock):
        self.product_id = product_id
        self.name = name
        self.price = price
        self.stock = stock

    def reduce_stock(self, quantity):
        """减少库存"""
        if quantity > self.stock:
            raise ValueError(f"库存不足,仅剩 {self.stock} 件")
        self.stock -= quantity

    def __str__(self):
        return f"{self.name}{self.price:.2f}, 库存: {self.stock})"

class OrderItem:
    """订单项"""

    def __init__(self, product, quantity):
        self.product = product
        self.quantity = quantity

    @property
    def subtotal(self):
        return self.product.price * self.quantity

    def __str__(self):
        return f"{self.product.name} x{self.quantity} = ¥{self.subtotal:.2f}"

class Order:
    """订单"""

    order_counter = 0  # 类属性:订单计数器

    def __init__(self, customer_name):
        Order.order_counter += 1
        self.order_id = f"ORD{Order.order_counter:06d}"
        self.customer_name = customer_name
        self.items = []
        self.status = OrderStatus.PENDING
        self.created_at = datetime.now()
        self.updated_at = self.created_at

    def add_item(self, product, quantity=1):
        """添加商品到订单"""
        if self.status != OrderStatus.PENDING:
            raise ValueError("只能向待支付订单添加商品")

        # 检查是否已存在相同商品
        for item in self.items:
            if item.product.product_id == product.product_id:
                item.quantity += quantity
                print(f"更新数量: {product.name} x{item.quantity}")
                return

        # 添加新商品
        item = OrderItem(product, quantity)
        self.items.append(item)
        print(f"添加商品: {product.name} x{quantity}")

    def remove_item(self, product_id):
        """移除商品"""
        if self.status != OrderStatus.PENDING:
            raise ValueError("只能从待支付订单移除商品")

        self.items = [item for item in self.items
                     if item.product.product_id != product_id]
        print(f"移除商品 ID: {product_id}")

    @property
    def total_amount(self):
        """订单总额"""
        return sum(item.subtotal for item in self.items)

    def pay(self):
        """支付订单"""
        if self.status != OrderStatus.PENDING:
            raise ValueError(f"订单状态不允许支付: {self.status.value}")

        if not self.items:
            raise ValueError("订单为空")

        # 扣减库存
        for item in self.items:
            item.product.reduce_stock(item.quantity)

        self.status = OrderStatus.PAID
        self.updated_at = datetime.now()
        print(f"✓ 订单 {self.order_id} 支付成功")

    def ship(self):
        """发货"""
        if self.status != OrderStatus.PAID:
            raise ValueError(f"订单状态不允许发货: {self.status.value}")

        self.status = OrderStatus.SHIPPED
        self.updated_at = datetime.now()
        print(f"✓ 订单 {self.order_id} 已发货")

    def deliver(self):
        """送达"""
        if self.status != OrderStatus.SHIPPED:
            raise ValueError(f"订单状态不允许送达: {self.status.value}")

        self.status = OrderStatus.DELIVERED
        self.updated_at = datetime.now()
        print(f"✓ 订单 {self.order_id} 已送达")

    def cancel(self):
        """取消订单"""
        if self.status not in [OrderStatus.PENDING, OrderStatus.PAID]:
            raise ValueError(f"订单状态不允许取消: {self.status.value}")

        # 恢复库存
        if self.status == OrderStatus.PAID:
            for item in self.items:
                item.product.stock += item.quantity

        self.status = OrderStatus.CANCELLED
        self.updated_at = datetime.now()
        print(f"✓ 订单 {self.order_id} 已取消")

    def display_order(self):
        """显示订单详情"""
        print(f"\n{'='*60}")
        print(f"订单号: {self.order_id}")
        print(f"客户: {self.customer_name}")
        print(f"状态: {self.status.value}")
        print(f"下单时间: {self.created_at}")
        print(f"更新时间: {self.updated_at}")
        print(f"{'-'*60}")

        if self.items:
            print("商品列表:")
            for item in self.items:
                print(f"  {item}")
            print(f"{'-'*60}")
            print(f"总计: ¥{self.total_amount:.2f}")
        else:
            print("订单为空")

        print(f"{'='*60}\n")

class ShoppingCart:
    """购物车"""

    def __init__(self, customer_name):
        self.customer_name = customer_name
        self.items = {}  # {product_id: {"product": product, "quantity": quantity}}

    def add_product(self, product, quantity=1):
        """添加商品"""
        if product.product_id in self.items:
            self.items[product.product_id]["quantity"] += quantity
        else:
            self.items[product.product_id] = {
                "product": product,
                "quantity": quantity
            }
        print(f"加入购物车: {product.name} x{quantity}")

    def remove_product(self, product_id):
        """移除商品"""
        if product_id in self.items:
            del self.items[product_id]
            print(f"移除商品 ID: {product_id}")

    def update_quantity(self, product_id, quantity):
        """更新数量"""
        if product_id in self.items:
            if quantity <= 0:
                self.remove_product(product_id)
            else:
                self.items[product_id]["quantity"] = quantity
                print(f"更新数量: {self.items[product_id]['product'].name} x{quantity}")

    @property
    def total_amount(self):
        """购物车总额"""
        return sum(
            item["product"].price * item["quantity"]
            for item in self.items.values()
        )

    def checkout(self):
        """结算:创建订单"""
        if not self.items:
            raise ValueError("购物车为空")

        order = Order(self.customer_name)

        for item_data in self.items.values():
            order.add_item(item_data["product"], item_data["quantity"])

        # 清空购物车
        self.items.clear()

        print(f"✓ 结算成功,创建订单 {order.order_id}")
        return order

    def display_cart(self):
        """显示购物车"""
        print(f"\n{'='*50}")
        print(f"购物车 - {self.customer_name}")
        print(f"{'-'*50}")

        if self.items:
            for item_data in self.items.values():
                product = item_data["product"]
                quantity = item_data["quantity"]
                subtotal = product.price * quantity
                print(f"{product.name} x{quantity} = ¥{subtotal:.2f}")

            print(f"{'-'*50}")
            print(f"总计: ¥{self.total_amount:.2f}")
        else:
            print("购物车为空")

        print(f"{'='*50}\n")

# 使用示例
# 创建商品
product1 = Product("P001", "iPhone 15", 7999, 100)
product2 = Product("P002", "MacBook Pro", 14999, 50)
product3 = Product("P003", "AirPods", 1299, 200)

# 创建购物车
cart = ShoppingCart("张三")
cart.add_product(product1, 1)
cart.add_product(product3, 2)
cart.display_cart()

# 结算
order = cart.checkout()
order.display_order()

# 支付流程
order.pay()
order.ship()
order.deliver()
order.display_order()

常见错误与注意事项

1. 忘记调用父类构造函数

# ❌ 错误
class Child(Parent):
    def __init__(self, name):
        self.name = name
        # 忘记调用 super().__init__()

# ✅ 正确
class Child(Parent):
    def __init__(self, name):
        super().__init__()  # 先调用父类构造函数
        self.name = name

2. 可变默认参数

# ❌ 危险
class Team:
    def __init__(self, members=[]):
        self.members = members

team1 = Team()
team2 = Team()
team1.members.append("Alice")
print(team2.members)  # ['Alice'](共享了同一个列表!)

# ✅ 正确
class Team:
    def __init__(self, members=None):
        self.members = members or []

3. 混淆类属性和实例属性

# ❌ 错误
class Dog:
    tricks = []  # 类属性,所有实例共享

    def add_trick(self, trick):
        self.tricks.append(trick)

dog1 = Dog()
dog2 = Dog()
dog1.add_trick("sit")
print(dog2.tricks)  # ['sit'](不期望的结果)

# ✅ 正确
class Dog:
    def __init__(self):
        self.tricks = []  # 实例属性

    def add_trick(self, trick):
        self.tricks.append(trick)

4. 过度使用继承

# ❌ 不推荐:过深的继承层次
class Animal:
    pass

class Mammal(Animal):
    pass

class Dog(Mammal):
    pass

class GoldenRetriever(Dog):
    pass

# ✅ 推荐:使用组合
class Breed:
    def __init__(self, name, characteristics):
        self.name = name
        self.characteristics = characteristics

class Dog:
    def __init__(self, name, breed):
        self.name = name
        self.breed = breed  # 组合而非继承

5. 滥用 getter/setter

# ❌ Java 风格(Python 中不必要)
class Person:
    def __init__(self, name):
        self._name = name

    def get_name(self):
        return self._name

    def set_name(self, name):
        self._name = name

# ✅ Pythonic 风格
class Person:
    def __init__(self, name):
        self.name = name  # 直接访问即可

# 需要验证时使用 @property
class Person:
    def __init__(self, name):
        self.name = name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        if not value:
            raise ValueError("名字不能为空")
        self._name = value

小结

概念说明使用场景
类和对象blueprint 和实例组织相关数据和方法
构造函数__init__ 初始化对象设置初始状态
实例方法操作实例数据对象的行为
类方法@classmethod 操作类工厂方法、替代构造
静态方法@staticmethod 工具函数与类相关但不依赖实例
封装隐藏实现细节保护数据完整性
继承代码复用和扩展"是一个"关系
多态同一接口不同实现灵活的设计
魔术方法自定义运算符和行为让类更像内置类型
属性装饰器@property 管理属性计算属性、验证
组合"有一个"关系构建复杂对象
抽象基类ABC 定义接口强制子类实现

核心要点

  • 面向对象是组织代码的强大工具
  • 优先使用组合而非继承
  • 遵循单一职责原则
  • 合理使用封装保护数据
  • 利用多态提高代码灵活性
  • Python 推崇简洁优雅的 OOP 风格
  • 理解魔术方法可以让类更 Pythonic

掌握面向对象编程将帮助你编写更清晰、可维护、可扩展的代码!