行莫
行莫
发布于 2025-11-17 / 3 阅读
0
0

3. Python 面向对象编程

3. Python 面向对象编程

引言

面向对象编程(Object-Oriented Programming, OOP)是一种强大的编程范式,它将数据和操作数据的方法组织在一起。Python 是一门完全支持面向对象的语言,理解 OOP 对于编写可维护、可扩展的代码至关重要。

本教程特点:

  • 每个概念都配有可直接运行的代码示例
  • 代码可以直接复制到 Python 解释器中执行
  • 循序渐进,从基础到高级
  • 包含实际应用场景和最佳实践

学习建议:

  1. 阅读每个示例代码
  2. 复制代码到 Python 解释器或 IDE 中运行
  3. 尝试修改代码,观察结果变化
  4. 完成每个部分的练习

第一部分:面向对象基础

1. 什么是类和对象?

类比理解

类(Class) 就像蓝图模板

  • 定义了一类事物的共同特征和行为
  • 例如:"汽车"这个类定义了所有汽车都有轮子、引擎等特征

对象(Object) 就像根据蓝图建造的房子

  • 是类的具体实例
  • 例如:一辆红色的特斯拉就是"汽车"类的一个对象

第一个类:定义和使用

# 示例 1:定义一个简单的类
class Dog:
    """这是一个表示狗的类"""
    
    def __init__(self, name, age):
        """初始化方法,创建对象时自动调用"""
        self.name = name  # self.name 是实例属性
        self.age = age
    
    def bark(self):
        """狗叫的方法"""
        return f"{self.name} 在叫:汪汪!"
    
    def get_info(self):
        """获取狗的信息"""
        return f"这是一只名叫 {self.name} 的狗,{self.age} 岁了"

# 创建对象(实例化)
dog1 = Dog("旺财", 3)
dog2 = Dog("小黑", 5)

# 使用对象
print(dog1.bark())        # 输出:旺财 在叫:汪汪!
print(dog2.get_info())    # 输出:这是一只名叫 小黑 的狗,5 岁了
print(dog1.name)          # 输出:旺财
print(dog1.age)           # 输出:3

运行结果:

旺财 在叫:汪汪!
这是一只名叫 小黑 的狗,5 岁了
旺财
3

关键概念解释

  1. class:定义类的关键字
  2. __init__:构造方法,创建对象时自动调用
  3. self:指向当前对象的引用
  4. 方法:定义在类中的函数
  5. 属性:对象的特征(如 name、age)

2. 属性和方法

实例属性

# 示例 2:实例属性的使用
class Student:
    def __init__(self, name, student_id, grade):
        self.name = name
        self.student_id = student_id
        self.grade = grade
        self.courses = []  # 可以初始化为列表
    
    def add_course(self, course_name):
        """添加课程"""
        self.courses.append(course_name)
        print(f"{self.name} 添加了课程:{course_name}")
    
    def show_courses(self):
        """显示所有课程"""
        if self.courses:
            print(f"{self.name} 的课程:{', '.join(self.courses)}")
        else:
            print(f"{self.name} 还没有选课")

# 创建学生对象
student1 = Student("张三", "2023001", 85)
student2 = Student("李四", "2023002", 90)

# 使用对象
student1.add_course("Python编程")
student1.add_course("数据结构")
student1.show_courses()

student2.add_course("机器学习")
student2.show_courses()

运行结果:

张三 添加了课程:Python编程
张三 添加了课程:数据结构
张三 的课程:Python编程, 数据结构
李四 添加了课程:机器学习
李四 的课程:机器学习

类属性

# 示例 3:类属性(所有实例共享)
class Circle:
    # 类属性
    pi = 3.14159
    count = 0  # 记录创建的圆的数量
    
    def __init__(self, radius):
        # 实例属性
        self.radius = radius
        Circle.count += 1  # 每次创建对象时,计数加1
    
    def area(self):
        """计算面积"""
        return Circle.pi * self.radius ** 2
    
    def circumference(self):
        """计算周长"""
        return 2 * Circle.pi * self.radius
    
    @classmethod
    def get_count(cls):
        """获取创建的圆的数量"""
        return cls.count

# 创建对象
circle1 = Circle(5)
circle2 = Circle(10)
circle3 = Circle(7)

# 访问类属性
print(f"π 的值:{Circle.pi}")
print(f"创建的圆的数量:{Circle.get_count()}")

# 使用实例方法
print(f"圆1的面积:{circle1.area():.2f}")
print(f"圆2的周长:{circle2.circumference():.2f}")

运行结果:

π 的值:3.14159
创建的圆的数量:3
圆1的面积:78.54
圆2的周长:62.83

第二部分:封装

1. 私有属性和方法

Python 使用命名约定来实现封装:以双下划线 __ 开头的属性和方法是私有的。

# 示例 4:私有属性和方法
class BankAccount:
    def __init__(self, account_number, initial_balance=0):
        self.account_number = account_number  # 公开属性
        self.__balance = initial_balance      # 私有属性(双下划线)
        self.__transaction_history = []       # 私有属性
    
    def deposit(self, amount):
        """存款"""
        if amount > 0:
            self.__balance += amount
            self.__transaction_history.append(f"存款:+{amount}")
            return f"存款成功,当前余额:{self.__balance}"
        else:
            return "存款金额必须大于0"
    
    def withdraw(self, amount):
        """取款"""
        if amount > 0 and amount <= self.__balance:
            self.__balance -= amount
            self.__transaction_history.append(f"取款:-{amount}")
            return f"取款成功,当前余额:{self.__balance}"
        else:
            return "取款失败:余额不足或金额无效"
    
    def get_balance(self):
        """获取余额(公开方法)"""
        return self.__balance
    
    def get_transaction_history(self):
        """获取交易历史"""
        return self.__transaction_history.copy()  # 返回副本,保护原始数据

# 创建账户
account = BankAccount("123456", 1000)

# 使用公开方法
print(account.deposit(500))
print(account.withdraw(200))
print(f"当前余额:{account.get_balance()}")

# 查看交易历史
print("交易历史:")
for transaction in account.get_transaction_history():
    print(f"  {transaction}")

# 尝试直接访问私有属性(不推荐,但Python允许通过特殊方式访问)
# print(account.__balance)  # 会报错:AttributeError
# print(account._BankAccount__balance)  # 可以访问,但不推荐

运行结果:

存款成功,当前余额:1500
取款成功,当前余额:1300
当前余额:1300
交易历史:
  存款:+500
  取款:-200

2. 属性装饰器(Property)

使用 @property 装饰器可以创建"计算属性",让访问属性像访问方法一样。

# 示例 5:使用 @property 装饰器
class Rectangle:
    def __init__(self, width, height):
        self._width = width   # 使用单下划线表示"受保护"的属性
        self._height = height
    
    @property
    def width(self):
        """获取宽度"""
        return self._width
    
    @width.setter
    def width(self, value):
        """设置宽度(带验证)"""
        if value > 0:
            self._width = value
        else:
            raise ValueError("宽度必须大于0")
    
    @property
    def height(self):
        """获取高度"""
        return self._height
    
    @height.setter
    def height(self, value):
        """设置高度(带验证)"""
        if value > 0:
            self._height = value
        else:
            raise ValueError("高度必须大于0")
    
    @property
    def area(self):
        """计算面积(只读属性)"""
        return self._width * self._height
    
    @property
    def perimeter(self):
        """计算周长(只读属性)"""
        return 2 * (self._width + self._height)

# 创建矩形
rect = Rectangle(5, 3)

# 像访问属性一样使用(不需要括号)
print(f"宽度:{rect.width}")
print(f"高度:{rect.height}")
print(f"面积:{rect.area}")
print(f"周长:{rect.perimeter}")

# 修改属性
rect.width = 10
rect.height = 6
print(f"\n修改后:")
print(f"宽度:{rect.width}")
print(f"面积:{rect.area}")

# 尝试设置无效值
try:
    rect.width = -5
except ValueError as e:
    print(f"错误:{e}")

运行结果:

宽度:5
高度:3
面积:15
周长:16

修改后:
宽度:10
面积:60
错误:宽度必须大于0

第三部分:继承

1. 单继承

继承允许我们创建一个新类,它继承父类的所有属性和方法。

# 示例 6:单继承
class Animal:
    """动物基类"""
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def eat(self):
        return f"{self.name} 在吃东西"
    
    def sleep(self):
        return f"{self.name} 在睡觉"
    
    def make_sound(self):
        return "动物发出声音"

class Dog(Animal):  # Dog 继承自 Animal
    """狗类"""
    def __init__(self, name, age, breed):
        super().__init__(name, age)  # 调用父类的初始化方法
        self.breed = breed
    
    def make_sound(self):  # 重写父类方法
        return f"{self.name} 在叫:汪汪!"
    
    def fetch(self):  # 子类特有的方法
        return f"{self.name} 在捡球"

class Cat(Animal):  # Cat 继承自 Animal
    """猫类"""
    def __init__(self, name, age, color):
        super().__init__(name, age)
        self.color = color
    
    def make_sound(self):  # 重写父类方法
        return f"{self.name} 在叫:喵喵!"
    
    def climb(self):  # 子类特有的方法
        return f"{self.name} 在爬树"

# 创建对象
dog = Dog("旺财", 3, "金毛")
cat = Cat("小花", 2, "橘色")

# 使用继承的方法
print(dog.eat())          # 继承自 Animal
print(dog.sleep())         # 继承自 Animal
print(dog.make_sound())    # 重写的方法
print(dog.fetch())         # 子类特有的方法

print("\n" + "="*30)

print(cat.eat())
print(cat.make_sound())
print(cat.climb())

运行结果:

旺财 在吃东西
旺财 在睡觉
旺财 在叫:汪汪!
旺财 在捡球
==============================
小花 在吃东西
小花 在叫:喵喵!
小花 在爬树

2. 多重继承

Python 支持多重继承,一个类可以继承多个父类。

# 示例 7:多重继承
class Flyable:
    """可飞行的能力"""
    def fly(self):
        return "正在飞行"
    
    def land(self):
        return "正在降落"

class Swimmable:
    """可游泳的能力"""
    def swim(self):
        return "正在游泳"
    
    def dive(self):
        return "正在潜水"

class Bird:
    """鸟类"""
    def __init__(self, name):
        self.name = name
    
    def make_sound(self):
        return "鸟在叫"

class Duck(Bird, Flyable, Swimmable):
    """鸭子:既是鸟,又能飞,又能游泳"""
    def __init__(self, name):
        super().__init__(name)
    
    def make_sound(self):
        return f"{self.name} 在叫:嘎嘎!"

# 创建鸭子对象
duck = Duck("唐老鸭")

# 可以使用所有继承的方法
print(duck.make_sound())
print(duck.fly())
print(duck.swim())
print(duck.dive())

# 查看方法解析顺序(MRO)
print(f"\n方法解析顺序:{Duck.__mro__}")

运行结果:

唐老鸭 在叫:嘎嘎!
正在飞行
正在游泳
正在潜水

方法解析顺序:(<class '__main__.Duck'>, <class '__main__.Bird'>, <class '__main__.Flyable'>, <class '__main__.Swimmable'>, <class 'object'>)

3. 方法重写和 super()

# 示例 8:方法重写和 super() 的使用
class Vehicle:
    """交通工具基类"""
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model
        self.speed = 0
    
    def start(self):
        self.speed = 10
        return f"{self.brand} {self.model} 启动了"
    
    def accelerate(self, increment=10):
        self.speed += increment
        return f"加速到 {self.speed} km/h"
    
    def stop(self):
        self.speed = 0
        return f"{self.brand} {self.model} 停止了"

class Car(Vehicle):
    """汽车类"""
    def __init__(self, brand, model, fuel_type):
        super().__init__(brand, model)  # 调用父类初始化
        self.fuel_type = fuel_type
    
    def start(self):
        # 先调用父类的方法
        result = super().start()
        return f"{result},使用 {self.fuel_type} 燃料"
    
    def accelerate(self, increment=20):  # 重写,默认增量不同
        return super().accelerate(increment)  # 调用父类方法

class Bicycle(Vehicle):
    """自行车类"""
    def __init__(self, brand, model, gear_count):
        super().__init__(brand, model)
        self.gear_count = gear_count
    
    def start(self):
        return f"{self.brand} {self.model} 开始骑行(人力驱动)"
    
    def accelerate(self, increment=5):  # 自行车加速较慢
        return super().accelerate(increment)

# 创建对象
car = Car("特斯拉", "Model 3", "电力")
bike = Bicycle("捷安特", "山地车", 21)

print("汽车:")
print(car.start())
print(car.accelerate())
print(car.accelerate(30))

print("\n自行车:")
print(bike.start())
print(bike.accelerate())
print(bike.accelerate(10))

运行结果:

汽车:
特斯拉 Model 3 启动了,使用 电力 燃料
加速到 30 km/h
加速到 60 km/h

自行车:
捷安特 山地车 开始骑行(人力驱动)
加速到 15 km/h
加速到 25 km/h

第四部分:多态

多态允许不同类的对象对同一消息做出不同的响应。

# 示例 9:多态
class Shape:
    """图形基类"""
    def area(self):
        raise NotImplementedError("子类必须实现 area 方法")
    
    def perimeter(self):
        raise NotImplementedError("子类必须实现 perimeter 方法")

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):
        return 3.14159 * self.radius ** 2
    
    def perimeter(self):
        return 2 * 3.14159 * self.radius

class Triangle(Shape):
    """三角形"""
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
    
    def area(self):
        # 海伦公式
        s = (self.a + self.b + self.c) / 2
        return (s * (s - self.a) * (s - self.b) * (s - self.c)) ** 0.5
    
    def perimeter(self):
        return self.a + self.b + self.c

# 多态的使用:不同对象调用相同的方法,产生不同的结果
def print_shape_info(shape):
    """这个函数可以处理任何 Shape 的子类"""
    print(f"面积:{shape.area():.2f}")
    print(f"周长:{shape.perimeter():.2f}")
    print()

# 创建不同的图形对象
shapes = [
    Rectangle(5, 3),
    Circle(4),
    Triangle(3, 4, 5)
]

# 使用多态:同一个函数处理不同类型的对象
for shape in shapes:
    print_shape_info(shape)

运行结果:

面积:15.00
周长:16.00

面积:50.27
周长:25.13

面积:6.00
周长:12.00

第五部分:特殊方法(魔术方法)

Python 提供了许多特殊方法(以双下划线开头和结尾),它们定义了对象的行为。

# 示例 10:特殊方法(魔术方法)
class Book:
    """图书类"""
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages
    
    def __str__(self):
        """字符串表示(用户友好)"""
        return f"《{self.title}》- {self.author}"
    
    def __repr__(self):
        """对象表示(开发者友好)"""
        return f"Book('{self.title}', '{self.author}', {self.pages})"
    
    def __len__(self):
        """返回书的页数"""
        return self.pages
    
    def __eq__(self, other):
        """相等比较"""
        if isinstance(other, Book):
            return self.title == other.title and self.author == other.author
        return False
    
    def __lt__(self, other):
        """小于比较(按页数)"""
        if isinstance(other, Book):
            return self.pages < other.pages
        return NotImplemented
    
    def __add__(self, other):
        """加法运算(合并两本书)"""
        if isinstance(other, Book):
            new_title = f"{self.title} & {other.title}"
            new_author = f"{self.author}, {other.author}"
            new_pages = self.pages + other.pages
            return Book(new_title, new_author, new_pages)
        return NotImplemented

# 创建图书对象
book1 = Book("Python编程", "张三", 300)
book2 = Book("数据结构", "李四", 250)
book3 = Book("Python编程", "张三", 300)

# 使用特殊方法
print("字符串表示:")
print(str(book1))      # 调用 __str__
print(repr(book1))     # 调用 __repr__

print(f"\n书的页数:{len(book1)}")  # 调用 __len__

print(f"\nbook1 == book3: {book1 == book3}")  # 调用 __eq__
print(f"book1 == book2: {book1 == book2}")

print(f"\nbook2 < book1: {book2 < book1}")  # 调用 __lt__

# 加法运算
combined_book = book1 + book2
print(f"\n合并后的书:{combined_book}")
print(f"总页数:{len(combined_book)}")

运行结果:

字符串表示:
《Python编程》- 张三
Book('Python编程', '张三', 300)

书的页数:300

book1 == book3: True
book1 == book2: False

book2 < book1: True

合并后的书:《Python编程 & 数据结构》- 张三, 李四
总页数:550

更多特殊方法示例

# 示例 11:更多特殊方法
class ShoppingCart:
    """购物车类"""
    def __init__(self):
        self.items = {}
    
    def add_item(self, item, quantity=1):
        """添加商品"""
        if item in self.items:
            self.items[item] += quantity
        else:
            self.items[item] = quantity
    
    def __getitem__(self, item):
        """支持索引访问:cart['苹果']"""
        return self.items.get(item, 0)
    
    def __setitem__(self, item, value):
        """支持索引赋值:cart['苹果'] = 5"""
        self.items[item] = value
    
    def __delitem__(self, item):
        """支持删除:del cart['苹果']"""
        if item in self.items:
            del self.items[item]
    
    def __contains__(self, item):
        """支持 in 操作符:'苹果' in cart"""
        return item in self.items
    
    def __iter__(self):
        """支持迭代:for item in cart"""
        return iter(self.items)
    
    def __len__(self):
        """返回商品种类数"""
        return len(self.items)
    
    def __str__(self):
        """字符串表示"""
        if not self.items:
            return "购物车是空的"
        items_str = ", ".join([f"{item}×{qty}" for item, qty in self.items.items()])
        return f"购物车:{items_str}"

# 创建购物车
cart = ShoppingCart()

# 添加商品
cart.add_item("苹果", 3)
cart.add_item("香蕉", 2)
cart.add_item("橙子", 5)

# 使用特殊方法
print(cart)
print(f"\n商品种类数:{len(cart)}")

# 索引访问
print(f"\n苹果数量:{cart['苹果']}")

# 索引赋值
cart['苹果'] = 10
print(f"修改后苹果数量:{cart['苹果']}")

# in 操作符
print(f"\n'苹果'在购物车中:{'苹果' in cart}")
print(f"'葡萄'在购物车中:{'葡萄' in cart}")

# 迭代
print("\n购物车中的商品:")
for item in cart:
    print(f"  {item}: {cart[item]}")

# 删除
del cart['橙子']
print(f"\n删除橙子后:{cart}")

运行结果:

购物车:苹果×3, 香蕉×2, 橙子×5

商品种类数:3

苹果数量:3
修改后苹果数量:10

'苹果'在购物车中:True
'葡萄'在购物车中:False

购物车中的商品:
  苹果: 10
  香蕉: 2
  橙子: 5

删除橙子后:购物车:苹果×10, 香蕉×2

第六部分:类方法和静态方法

1. 类方法(@classmethod)

类方法属于类而不是实例,第一个参数是类本身(通常命名为 cls)。

# 示例 12:类方法
class Person:
    """人类"""
    population = 0  # 类属性:总人口数
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
        Person.population += 1
    
    @classmethod
    def get_population(cls):
        """获取总人口数"""
        return cls.population
    
    @classmethod
    def create_baby(cls, name):
        """创建一个婴儿(年龄为0)"""
        return cls(name, 0)
    
    @classmethod
    def from_birth_year(cls, name, birth_year):
        """根据出生年份创建对象"""
        from datetime import datetime
        age = datetime.now().year - birth_year
        return cls(name, age)
    
    def __str__(self):
        return f"{self.name}, {self.age}岁"

# 使用类方法
print(f"初始人口:{Person.get_population()}")

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

print(f"创建3个人后,人口:{Person.get_population()}")

# 使用类方法创建对象
baby = Person.create_baby("小明")
print(f"\n使用类方法创建婴儿:{baby}")

# 使用类方法根据出生年份创建
person4 = Person.from_birth_year("赵六", 1995)
print(f"根据出生年份创建:{person4}")

print(f"\n最终人口:{Person.get_population()}")

运行结果:

初始人口:0
创建3个人后,人口:3

使用类方法创建婴儿:小明, 0岁
根据出生年份创建:赵六, 29岁

最终人口:5

2. 静态方法(@staticmethod)

静态方法不需要访问类或实例,它只是一个普通的函数,但逻辑上属于这个类。

# 示例 13:静态方法
class MathUtils:
    """数学工具类"""
    
    @staticmethod
    def add(a, b):
        """加法"""
        return a + b
    
    @staticmethod
    def multiply(a, b):
        """乘法"""
        return a * b
    
    @staticmethod
    def is_even(number):
        """判断是否为偶数"""
        return number % 2 == 0
    
    @staticmethod
    def factorial(n):
        """计算阶乘"""
        if n < 0:
            raise ValueError("阶乘不能为负数")
        if n == 0 or n == 1:
            return 1
        result = 1
        for i in range(2, n + 1):
            result *= i
        return result

# 使用静态方法(可以通过类或实例调用)
print("通过类调用:")
print(f"5 + 3 = {MathUtils.add(5, 3)}")
print(f"5 × 3 = {MathUtils.multiply(5, 3)}")
print(f"6是偶数:{MathUtils.is_even(6)}")
print(f"5! = {MathUtils.factorial(5)}")

# 也可以通过实例调用
utils = MathUtils()
print(f"\n通过实例调用:")
print(f"10 + 20 = {utils.add(10, 20)}")

运行结果:

通过类调用:
5 + 3 = 8
5 × 3 = 15
6是偶数:True
5! = 120

通过实例调用:
10 + 20 = 30

第七部分:实际应用示例

1. 学生管理系统

# 示例 14:学生管理系统
class Student:
    """学生类"""
    def __init__(self, student_id, name, age):
        self.student_id = student_id
        self.name = name
        self.age = age
        self.courses = {}  # {课程名: 成绩}
    
    def enroll_course(self, course_name):
        """选课"""
        if course_name not in self.courses:
            self.courses[course_name] = None
            return f"{self.name} 成功选课:{course_name}"
        return f"{self.name} 已经选了 {course_name}"
    
    def set_grade(self, course_name, grade):
        """设置成绩"""
        if course_name in self.courses:
            self.courses[course_name] = grade
            return f"{self.name}{course_name} 成绩已设置为 {grade}"
        return f"{self.name} 没有选 {course_name} 这门课"
    
    def get_average_grade(self):
        """计算平均成绩"""
        grades = [g for g in self.courses.values() if g is not None]
        if grades:
            return sum(grades) / len(grades)
        return None
    
    def __str__(self):
        avg = self.get_average_grade()
        avg_str = f"{avg:.2f}" if avg else "暂无成绩"
        return f"学生[{self.student_id}] {self.name}, {self.age}岁, 平均分:{avg_str}"

class Course:
    """课程类"""
    def __init__(self, course_id, name, teacher):
        self.course_id = course_id
        self.name = name
        self.teacher = teacher
        self.students = []
    
    def add_student(self, student):
        """添加学生"""
        if student not in self.students:
            self.students.append(student)
            student.enroll_course(self.name)
            return f"{student.name} 已添加到 {self.name}"
        return f"{student.name} 已经在 {self.name} 课程中"
    
    def __str__(self):
        return f"课程[{self.course_id}] {self.name}, 授课教师:{self.teacher}, 学生数:{len(self.students)}"

# 创建学生
student1 = Student("2023001", "张三", 20)
student2 = Student("2023002", "李四", 21)
student3 = Student("2023003", "王五", 19)

# 创建课程
python_course = Course("CS101", "Python编程", "张老师")
math_course = Course("MA101", "高等数学", "李老师")

# 学生选课
python_course.add_student(student1)
python_course.add_student(student2)
python_course.add_student(student3)

math_course.add_student(student1)
math_course.add_student(student2)

# 设置成绩
student1.set_grade("Python编程", 85)
student1.set_grade("高等数学", 90)
student2.set_grade("Python编程", 92)
student2.set_grade("高等数学", 88)
student3.set_grade("Python编程", 78)

# 显示信息
print("课程信息:")
print(python_course)
print(math_course)

print("\n学生信息:")
print(student1)
print(student2)
print(student3)

运行结果:

课程信息:
课程[CS101] Python编程, 授课教师:张老师, 学生数:3
课程[MA101] 高等数学, 授课教师:李老师, 学生数:2

学生信息:
学生[2023001] 张三, 20岁, 平均分:87.50
学生[2023002] 李四, 21岁, 平均分:90.00
学生[2023003] 王五, 19岁, 平均分:78.00

2. 图书管理系统

# 示例 15:图书管理系统
class Book:
    """图书类"""
    total_books = 0
    
    def __init__(self, isbn, title, author, price):
        self.isbn = isbn
        self.title = title
        self.author = author
        self.price = price
        self.is_available = True
        Book.total_books += 1
    
    def borrow(self):
        """借书"""
        if self.is_available:
            self.is_available = False
            return f"《{self.title}》已借出"
        return f"《{self.title}》已被借出,无法借阅"
    
    def return_book(self):
        """还书"""
        if not self.is_available:
            self.is_available = True
            return f"《{self.title}》已归还"
        return f"《{self.title}》未被借出"
    
    def __str__(self):
        status = "可借" if self.is_available else "已借出"
        return f"《{self.title}》- {self.author}, 价格:¥{self.price}, 状态:{status}"
    
    @classmethod
    def get_total_books(cls):
        return cls.total_books

class Library:
    """图书馆类"""
    def __init__(self, name):
        self.name = name
        self.books = {}
    
    def add_book(self, book):
        """添加图书"""
        self.books[book.isbn] = book
        return f"已添加图书:{book.title}"
    
    def find_book(self, isbn):
        """查找图书"""
        return self.books.get(isbn)
    
    def search_by_title(self, keyword):
        """按书名搜索"""
        results = []
        for book in self.books.values():
            if keyword.lower() in book.title.lower():
                results.append(book)
        return results
    
    def list_available_books(self):
        """列出可借图书"""
        return [book for book in self.books.values() if book.is_available]
    
    def __str__(self):
        return f"{self.name},共有 {len(self.books)} 本图书"

# 创建图书馆
library = Library("市图书馆")

# 添加图书
book1 = Book("978-7-111-12345-1", "Python编程", "张三", 59.9)
book2 = Book("978-7-111-12345-2", "数据结构", "李四", 49.9)
book3 = Book("978-7-111-12345-3", "机器学习", "王五", 79.9)

library.add_book(book1)
library.add_book(book2)
library.add_book(book3)

print(library)
print(f"\n图书馆中共有 {Book.get_total_books()} 本图书")

# 显示所有图书
print("\n所有图书:")
for book in library.books.values():
    print(f"  {book}")

# 借书
print(f"\n{book1.borrow()}")
print(f"{book1}")

# 搜索图书
print("\n搜索'Python':")
results = library.search_by_title("Python")
for book in results:
    print(f"  {book}")

# 列出可借图书
print("\n可借图书:")
available = library.list_available_books()
for book in available:
    print(f"  {book}")

运行结果:

市图书馆,共有 3 本图书

图书馆中共有 3 本图书

所有图书:
  《Python编程》- 张三, 价格:¥59.9, 状态:可借
  《数据结构》- 李四, 价格:¥49.9, 状态:可借
  《机器学习》- 王五, 价格:¥79.9, 状态:可借

《Python编程》已借出
《Python编程》- 张三, 价格:¥59.9, 状态:已借出

搜索'Python':
  《Python编程》- 张三, 价格:¥59.9, 状态:已借出

可借图书:
  《数据结构》- 李四, 价格:¥49.9, 状态:可借
  《机器学习》- 王五, 价格:¥79.9, 状态:可借

第八部分:设计模式示例

1. 单例模式

# 示例 16:单例模式
class Singleton:
    """单例模式:确保一个类只有一个实例"""
    _instance = None
    
    def __new__(cls):
        """重写 __new__ 方法"""
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def __init__(self):
        """初始化(只会执行一次)"""
        if not hasattr(self, 'initialized'):
            self.value = None
            self.initialized = True

# 测试单例模式
singleton1 = Singleton()
singleton1.value = "第一个实例"

singleton2 = Singleton()
singleton2.value = "第二个实例"

print(f"singleton1.value: {singleton1.value}")
print(f"singleton2.value: {singleton2.value}")
print(f"singleton1 is singleton2: {singleton1 is singleton2}")

运行结果:

singleton1.value: 第二个实例
singleton2.value: 第二个实例
singleton1 is singleton2: True

2. 工厂模式

# 示例 17:工厂模式
class Animal:
    """动物基类"""
    def speak(self):
        raise NotImplementedError

class Dog(Animal):
    def speak(self):
        return "汪汪!"

class Cat(Animal):
    def speak(self):
        return "喵喵!"

class Duck(Animal):
    def speak(self):
        return "嘎嘎!"

class AnimalFactory:
    """动物工厂"""
    @staticmethod
    def create_animal(animal_type):
        """根据类型创建动物"""
        animals = {
            "dog": Dog,
            "cat": Cat,
            "duck": Duck
        }
        animal_class = animals.get(animal_type.lower())
        if animal_class:
            return animal_class()
        raise ValueError(f"未知的动物类型:{animal_type}")

# 使用工厂创建对象
factory = AnimalFactory()

dog = factory.create_animal("dog")
cat = factory.create_animal("cat")
duck = factory.create_animal("duck")

print(f"狗说:{dog.speak()}")
print(f"猫说:{cat.speak()}")
print(f"鸭子说:{duck.speak()}")

运行结果:

狗说:汪汪!
猫说:喵喵!
鸭子说:嘎嘎!

第九部分:最佳实践和常见错误

1. 命名约定

# 示例 18:Python 命名约定
class MyClass:
    """类名使用驼峰命名法(PascalCase)"""
    
    # 公开属性:普通命名
    public_attr = "公开属性"
    
    # 受保护属性:单下划线开头(约定,不是强制)
    _protected_attr = "受保护属性"
    
    # 私有属性:双下划线开头
    __private_attr = "私有属性"
    
    # 公开方法:普通命名
    def public_method(self):
        return "公开方法"
    
    # 受保护方法:单下划线开头
    def _protected_method(self):
        return "受保护方法"
    
    # 私有方法:双下划线开头
    def __private_method(self):
        return "私有方法"
    
    # 特殊方法:双下划线开头和结尾
    def __str__(self):
        return "特殊方法"

# 方法名使用蛇形命名法(snake_case)
def my_function():
    pass

# 常量使用全大写
MAX_SIZE = 100
DEFAULT_VALUE = 0

2. 常见错误和解决方案

# 示例 19:常见错误和解决方案

# 错误1:忘记 self 参数
class BadExample1:
    def method():  # ❌ 缺少 self
        return "错误"

# 正确做法:
class GoodExample1:
    def method(self):  # ✅ 有 self
        return "正确"

# 错误2:在类外部修改可变默认参数
class BadExample2:
    def __init__(self, items=[]):  # ❌ 可变默认参数
        self.items = items

# 正确做法:
class GoodExample2:
    def __init__(self, items=None):  # ✅ 使用 None
        self.items = items if items is not None else []

# 错误3:直接访问私有属性
class BadExample3:
    def __init__(self):
        self.__value = 10
    
    def get_value(self):
        return self.__value  # ✅ 通过方法访问

# 使用示例
obj = GoodExample2()
print(f"items: {obj.items}")

obj2 = GoodExample2([1, 2, 3])
print(f"items: {obj2.items}")

第十部分:练习和总结

练习1:创建一个银行账户类

# 练习1:创建银行账户类
# 要求:
# 1. 有账户号和余额属性
# 2. 有存款、取款方法
# 3. 取款时检查余额是否足够
# 4. 有获取余额的方法

class BankAccount:
    # 在这里实现你的代码
    pass

# 测试代码
# account = BankAccount("123456", 1000)
# account.deposit(500)
# account.withdraw(200)
# print(account.get_balance())

练习2:创建一个图形类层次结构

# 练习2:创建图形类层次结构
# 要求:
# 1. 创建一个 Shape 基类
# 2. 创建 Rectangle、Circle、Triangle 子类
# 3. 每个子类实现 area() 和 perimeter() 方法
# 4. 使用多态打印所有图形的面积和周长

# 在这里实现你的代码

总结

核心概念:

  1. 类(Class):定义对象的模板
  2. 对象(Object):类的实例
  3. 封装(Encapsulation):隐藏内部实现细节
  4. 继承(Inheritance):代码复用和扩展
  5. 多态(Polymorphism):同一接口,不同实现

关键特性:

  • __init__:构造方法
  • self:指向当前对象
  • super():调用父类方法
  • @property:属性装饰器
  • @classmethod:类方法
  • @staticmethod:静态方法
  • 特殊方法__str__, __repr__, __len__

最佳实践:

  1. 使用有意义的类名和方法名
  2. 遵循命名约定
  3. 使用文档字符串(docstring)
  4. 合理使用封装保护数据
  5. 利用继承减少代码重复
  6. 使用多态提高代码灵活性

附录:完整示例代码

完整的面向对象示例:游戏角色系统

# 完整的面向对象示例:游戏角色系统
class Character:
    """游戏角色基类"""
    def __init__(self, name, health, attack_power):
        self.name = name
        self.health = health
        self.max_health = health
        self.attack_power = attack_power
        self.level = 1
        self.experience = 0
    
    def attack(self, target):
        """攻击目标"""
        damage = self.attack_power
        target.take_damage(damage)
        return f"{self.name} 攻击了 {target.name},造成 {damage} 点伤害"
    
    def take_damage(self, damage):
        """受到伤害"""
        self.health = max(0, self.health - damage)
        if self.health == 0:
            return f"{self.name} 被击败了!"
        return f"{self.name} 受到 {damage} 点伤害,剩余生命值:{self.health}"
    
    def heal(self, amount):
        """治疗"""
        self.health = min(self.max_health, self.health + amount)
        return f"{self.name} 恢复了 {amount} 点生命值,当前生命值:{self.health}"
    
    def gain_experience(self, exp):
        """获得经验值"""
        self.experience += exp
        # 简单的升级逻辑:每100经验升1级
        new_level = self.experience // 100 + 1
        if new_level > self.level:
            self.level = new_level
            self.max_health += 10
            self.health = self.max_health
            self.attack_power += 5
            return f"{self.name} 升级了!当前等级:{self.level}"
        return f"{self.name} 获得 {exp} 点经验值"
    
    def __str__(self):
        return f"{self.name} (Lv.{self.level}) - HP: {self.health}/{self.max_health}, 攻击力: {self.attack_power}"

class Warrior(Character):
    """战士类"""
    def __init__(self, name):
        super().__init__(name, health=100, attack_power=15)
        self.armor = 5
    
    def take_damage(self, damage):
        """战士有护甲,减少伤害"""
        actual_damage = max(1, damage - self.armor)
        return super().take_damage(actual_damage)
    
    def charge(self, target):
        """冲锋攻击(额外伤害)"""
        damage = self.attack_power * 2
        target.take_damage(damage)
        return f"{self.name}{target.name} 发动冲锋,造成 {damage} 点伤害!"

class Mage(Character):
    """法师类"""
    def __init__(self, name):
        super().__init__(name, health=60, attack_power=20)
        self.mana = 100
        self.max_mana = 100
    
    def fireball(self, target):
        """火球术(消耗法力)"""
        if self.mana >= 30:
            self.mana -= 30
            damage = self.attack_power * 2
            target.take_damage(damage)
            return f"{self.name}{target.name} 释放火球术,造成 {damage} 点伤害!"
        return f"{self.name} 法力不足,无法释放火球术"
    
    def meditate(self):
        """冥想(恢复法力)"""
        self.mana = min(self.max_mana, self.mana + 50)
        return f"{self.name} 冥想恢复法力,当前法力:{self.mana}/{self.max_mana}"
    
    def __str__(self):
        base_str = super().__str__()
        return f"{base_str}, 法力: {self.mana}/{self.max_mana}"

# 游戏演示
print("=" * 50)
print("游戏角色系统演示")
print("=" * 50)

# 创建角色
warrior = Warrior("战士")
mage = Mage("法师")

print(f"\n初始状态:")
print(warrior)
print(mage)

# 战斗
print(f"\n战斗开始:")
print(warrior.attack(mage))
print(mage)

print(mage.fireball(warrior))
print(warrior)

print(warrior.charge(mage))
print(mage)

# 治疗和恢复
print(f"\n恢复:")
print(warrior.heal(20))
print(mage.meditate())

# 获得经验
print(f"\n获得经验:")
print(warrior.gain_experience(150))
print(warrior)

print(f"\n最终状态:")
print(warrior)
print(mage)

运行结果:

==================================================
游戏角色系统演示
==================================================

初始状态:
战士 (Lv.1) - HP: 100/100, 攻击力: 15
法师 (Lv.1) - HP: 60/60, 攻击力: 20, 法力: 100/100

战斗开始:
战士 攻击了 法师,造成 15 点伤害
法师 (Lv.1) - HP: 45/60, 攻击力: 20, 法力: 100/100
法师 对 战士 释放火球术,造成 40 点伤害!
战士 (Lv.1) - HP: 95/100, 攻击力: 15
战士 对 法师 发动冲锋,造成 30 点伤害!
法师 (Lv.1) - HP: 15/60, 攻击力: 20, 法力: 70/100

恢复:
战士 恢复了 20 点生命值,当前生命值:100
法师 冥想恢复法力,当前法力:100/100

获得经验:
战士 升级了!当前等级:2
战士 (Lv.2) - HP: 110/110, 攻击力: 20

最终状态:
战士 (Lv.2) - HP: 110/110, 攻击力: 20
法师 (Lv.1) - HP: 15/60, 攻击力: 20, 法力: 100/100

总结

本教程涵盖了 Python 面向对象编程的核心概念:

  1. 基础概念:类、对象、属性、方法
  2. 封装:私有属性、属性装饰器
  3. 继承:单继承、多重继承、方法重写
  4. 多态:同一接口,不同实现
  5. 特殊方法__init__, __str__, __repr__
  6. 类方法和静态方法@classmethod, @staticmethod
  7. 实际应用:学生管理、图书管理等系统
  8. 设计模式:单例模式、工厂模式

下一步学习建议:

  1. 练习编写自己的类和对象
  2. 学习更多设计模式
  3. 了解 Python 的元类(metaclass)
  4. 学习装饰器的深入应用
  5. 阅读优秀的开源代码,学习面向对象设计

记住:面向对象编程的核心思想是将数据和操作数据的方法组织在一起,让代码更加模块化、可维护、可扩展。多练习、多思考,你就能掌握面向对象编程的精髓!


祝你编程愉快! 🐍✨


评论