Python3:面向对象编程

这里写目录标题

    • 面向对象编程:让代码化身为积木世界
      • 一、核心概念:类与对象
      • 二、四大基石:面向对象的核心特性
        • 1️⃣ 封装(Encapsulation):包装复杂性,提供简单接口
        • 2️⃣ 继承(Inheritance):站在巨人的肩膀上
        • 3️⃣ 多态(Polymorphism):一个接口,多种形态
        • 4️⃣ 抽象(Abstraction):提炼共性,忽略细节
      • 三、特殊方法(魔术方法):Python类的超能力
      • 四、属性装饰器:优雅地访问和修改属性
      • 五、类方法与静态方法:超越实例的方法
      • 六、组合与继承:两种代码复用的方式
      • 七、单例模式:确保类只有一个实例
      • 八、多重继承与MRO:处理复杂继承关系
      • 九、设计模式:解决常见问题的经验总结
        • 工厂模式:创建对象的接口
        • 观察者模式:对象状态变化时通知其他对象
      • 实际项目应用:小型代码管理系统
      • 总结
    • 练习
      • 1. 创建一个动物园系统
      • 2.实现一个简单的银行系统
      • 3.开发一个命令行游戏
      • 4.创建一个自定义容器

面向对象编程:让代码化身为积木世界

想象一下,如果编程是搭建乐高积木,那么面向对象编程(OOP)就是创造了一套可以自定义形状、功能和行为的积木系统。不再局限于使用现成的积木,你可以设计自己的积木类型!

一、核心概念:类与对象

类(Class) 是蓝图,对象(Object) 是实体。

想象你有一个"蛋糕模具"(类),你可以用它制作出无数个"蛋糕"(对象)。每个蛋糕都有相同的基本结构(属性),但可以有不同的口味、装饰(状态)。

# 定义一个蛋糕类
class Cake:
    def __init__(self, flavor, layers):
        self.flavor = flavor    # 属性:口味
        self.layers = layers    # 属性:层数
        self.is_baked = False   # 属性:是否烤好
    
    def bake(self, time):       # 方法:烘焙
        print(f"烘焙{self.flavor}蛋糕 {time} 分钟...")
        self.is_baked = True
    
    def add_topping(self, topping):  # 方法:添加装饰
        print(f"在{self.flavor}蛋糕上添加{topping}")

# 创建两个不同的蛋糕对象
chocolate_cake = Cake("巧克力", 3)
strawberry_cake = Cake("草莓", 2)

# 使用对象的方法
chocolate_cake.bake(30)
chocolate_cake.add_topping("巧克力碎片")

strawberry_cake.bake(25)
strawberry_cake.add_topping("新鲜草莓")

二、四大基石:面向对象的核心特性

1️⃣ 封装(Encapsulation):包装复杂性,提供简单接口

就像使用咖啡机,你只需要按按钮,不需要了解内部工作原理。封装让我们隐藏复杂的实现细节,只暴露必要的功能。

class BankAccount:
    def __init__(self, owner, initial_balance=0):
        self.owner = owner
        self.__balance = initial_balance  # 私有属性,外部不能直接访问
    
    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return True
        return False
    
    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            return True
        return False
    
    def get_balance(self):
        return self.__balance  # 通过方法访问私有属性

# 使用银行账户
account = BankAccount("张三", 1000)
account.deposit(500)
print(account.get_balance())  # 1500

# 无法直接访问私有属性
# print(account.__balance)  # 这会报错!

在Python中,单下划线(_)表示"内部使用",双下划线(__)表示"私有"。实际上,Python会将__balance转换为_BankAccount__balance,这种命名改写称为名称修饰(name mangling)。

2️⃣ 继承(Inheritance):站在巨人的肩膀上

继承允许一个类(子类)获得另一个类(父类)的所有属性和方法。这就像孩子继承了父母的特征,但可以发展自己的特性。

# 父类
class Animal:
    def __init__(self, name, species):
        self.name = name
        self.species = species
    
    def make_sound(self):
        print("某种动物声音")
    
    def info(self):
        print(f"我是{self.name},一只{self.species}")

# 子类
class Dog(Animal):
    def __init__(self, name, breed):
        # 调用父类的初始化方法
        super().__init__(name, "狗")
        self.breed = breed
    
    # 重写父类方法
    def make_sound(self):
        print("汪汪!")
    
    # 添加新方法
    def fetch(self):
        print(f"{self.name}去捡球了!")

# 创建对象
animal = Animal("未知", "某种动物")
dog = Dog("旺财", "金毛")

animal.info()  # 我是未知,一只某种动物
dog.info()     # 我是旺财,一只狗

animal.make_sound()  # 某种动物声音
dog.make_sound()     # 汪汪!

dog.fetch()  # 旺财去捡球了!
3️⃣ 多态(Polymorphism):一个接口,多种形态

多态允许不同类的对象对同一消息做出不同的响应。这就像按下"播放"按钮,音乐播放器播放音乐,视频播放器播放视频。

# 继续使用前面的Animal类体系
def make_animal_sound(animal):
    animal.make_sound()  # 不关心具体是什么动物,只调用make_sound方法

class Cat(Animal):
    def __init__(self, name, color):
        super().__init__(name, "猫")
        self.color = color
    
    def make_sound(self):
        print("喵喵!")

# 创建不同动物
dog = Dog("旺财", "金毛")
cat = Cat("咪咪", "橘色")

# 同一个函数可以处理不同类型的对象
make_animal_sound(dog)  # 汪汪!
make_animal_sound(cat)  # 喵喵!
4️⃣ 抽象(Abstraction):提炼共性,忽略细节

抽象让我们专注于对象的"是什么"和"能做什么",而不是"怎么做"。在Python中,我们可以通过abc模块实现抽象类。

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

class Rectangle(Shape):
    def __init__(self, length, width):
        self.length = length
        self.width = width
    
    def area(self):
        return self.length * self.width
    
    def perimeter(self):
        return 2 * (self.length + self.width)

# 不能创建抽象类的实例
# shape = Shape()  # 这会报错!

# 创建具体形状
circle = Circle(5)
rectangle = Rectangle(4, 6)

print(f"圆的面积: {circle.area()}")
print(f"矩形的面积: {rectangle.area()}")

三、特殊方法(魔术方法):Python类的超能力

Python类有许多特殊方法,以双下划线开头和结尾,如__init____str__等。这些方法可以让我们自定义对象的行为。

class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages
        self.current_page = 0
    
    # 定义对象的字符串表示
    def __str__(self):
        return f"{self.title} by {self.author}"
    
    # 定义对象的官方表示
    def __repr__(self):
        return f"Book('{self.title}', '{self.author}', {self.pages})"
    
    # 定义对象的长度
    def __len__(self):
        return self.pages
    
    # 定义对象的布尔值
    def __bool__(self):
        return self.pages > 0
    
    # 使对象可以像函数一样被调用
    def __call__(self, page):
        if 0 <= page < self.pages:
            self.current_page = page
            return f"翻到了第{page}页"
        return "无效页码"

# 创建书籍对象
book = Book("Python大冒险", "编程达人", 300)

print(str(book))       # Python大冒险 by 编程达人
print(repr(book))      # Book('Python大冒险', '编程达人', 300)
print(len(book))       # 300
print(bool(book))      # True
print(book(100))       # 翻到了第100页

四、属性装饰器:优雅地访问和修改属性

使用属性装饰器,我们可以像访问属性一样调用方法,使代码更加简洁优雅。

class Temperature:
    def __init__(self, celsius=0):
        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
    
    @fahrenheit.setter
    def fahrenheit(self, value):
        self.celsius = (value - 32) * 5/9

# 创建温度对象
temp = Temperature(25)

# 像访问属性一样使用getter
print(temp.celsius)     # 25
print(temp.fahrenheit)  # 77.0

# 像修改属性一样使用setter
temp.celsius = 30
print(temp.fahrenheit)  # 86.0

temp.fahrenheit = 68
print(temp.celsius)     # 20.0

# 设置无效温度会引发异常
# temp.celsius = -300  # ValueError: 温度不能低于绝对零度

五、类方法与静态方法:超越实例的方法

除了常规的实例方法,Python类还可以有类方法和静态方法。

class Pizza:
    total_pizzas = 0  # 类变量
    
    def __init__(self, size, toppings):
        self.size = size
        self.toppings = toppings
        Pizza.total_pizzas += 1
    
    # 实例方法:需要访问实例属性
    def get_description(self):
        toppings_str = ", ".join(self.toppings)
        return f"{self.size}寸披萨,配料:{toppings_str}"
    
    # 类方法:需要访问类属性
    @classmethod
    def get_total(cls):
        return f"总共制作了{cls.total_pizzas}个披萨"
    
    # 类方法作为替代构造函数
    @classmethod
    def create_cheese_pizza(cls, size):
        return cls(size, ["奶酪"])
    
    # 静态方法:不需要访问实例或类属性
    @staticmethod
    def is_valid_size(size):
        return size in [6, 9, 12, 18]

# 创建披萨
pizza1 = Pizza(12, ["奶酪", "蘑菇", "青椒"])
pizza2 = Pizza(9, ["奶酪", "香肠"])

# 调用实例方法
print(pizza1.get_description())  # 12寸披萨,配料:奶酪, 蘑菇, 青椒

# 调用类方法
print(Pizza.get_total())  # 总共制作了2个披萨

# 使用类方法作为替代构造函数
cheese_pizza = Pizza.create_cheese_pizza(18)
print(cheese_pizza.get_description())  # 18寸披萨,配料:奶酪

# 调用静态方法
print(Pizza.is_valid_size(12))  # True
print(Pizza.is_valid_size(7))   # False

六、组合与继承:两种代码复用的方式

继承表示"是一个"关系,组合表示"有一个"关系。通常,组合比继承更灵活。

# 组合示例
class Engine:
    def __init__(self, power):
        self.power = power
    
    def start(self):
        return f"引擎启动,功率{self.power}马力"

class Radio:
    def __init__(self, brand):
        self.brand = brand
    
    def play_music(self):
        return f"{self.brand}音响播放音乐"

# 汽车通过组合使用引擎和收音机
class Car:
    def __init__(self, model, engine_power, radio_brand):
        self.model = model
        self.engine = Engine(engine_power)  # 组合
        self.radio = Radio(radio_brand)     # 组合
    
    def start_journey(self):
        return f"{self.model}{self.engine.start()}{self.radio.play_music()}"

# 创建汽车
my_car = Car("特斯拉Model 3", 300, "哈曼卡顿")
print(my_car.start_journey())
# 特斯拉Model 3:引擎启动,功率300马力,哈曼卡顿音响播放音乐

七、单例模式:确保类只有一个实例

有时我们需要确保一个类只有一个实例,比如配置管理器、数据库连接池等。

class Singleton:
    _instance = None
    
    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

class ConfigManager(Singleton):
    def __init__(self):
        # 这里仅在第一次创建实例时初始化
        if not hasattr(self, 'config'):
            self.config = {
                'debug': True,
                'log_level': 'INFO',
                'max_connections': 100
            }
    
    def get_config(self, key):
        return self.config.get(key)
    
    def set_config(self, key, value):
        self.config[key] = value

# 创建两个实例
config1 = ConfigManager()
config2 = ConfigManager()

# 它们是同一个对象
print(config1 is config2)  # True

# 通过一个实例修改配置
config1.set_config('debug', False)

# 另一个实例也会受到影响
print(config2.get_config('debug'))  # False

八、多重继承与MRO:处理复杂继承关系

Python允许一个类继承多个父类,但这可能导致方法解析顺序(MRO)的问题。

class A:
    def who_am_i(self):
        return "I am A"

class B(A):
    def who_am_i(self):
        return "I am B"

class C(A):
    def who_am_i(self):
        return "I am C"

# D同时继承B和C
class D(B, C):
    pass

# 查看MRO
print(D.__mro__)
# (, , , , )

# 调用方法
d = D()
print(d.who_am_i())  # I am B (因为B在MRO中排在C前面)

九、设计模式:解决常见问题的经验总结

面向对象编程中,设计模式是对常见问题的解决方案。以下是一些常见的设计模式:

工厂模式:创建对象的接口
class Animal:
    def speak(self):
        pass

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

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

class AnimalFactory:
    def create_animal(self, animal_type):
        if animal_type == "dog":
            return Dog()
        elif animal_type == "cat":
            return Cat()
        else:
            raise ValueError(f"不支持的动物类型: {animal_type}")

# 使用工厂
factory = AnimalFactory()
dog = factory.create_animal("dog")
cat = factory.create_animal("cat")

print(dog.speak())  # 汪汪!
print(cat.speak())  # 喵喵!
观察者模式:对象状态变化时通知其他对象
class Subject:
    def __init__(self):
        self._observers = []
    
    def attach(self, observer):
        if observer not in self._observers:
            self._observers.append(observer)
    
    def detach(self, observer):
        self._observers.remove(observer)
    
    def notify(self, message):
        for observer in self._observers:
            observer.update(message)

class Observer:
    def __init__(self, name):
        self.name = name
    
    def update(self, message):
        print(f"{self.name} 收到消息: {message}")

# 创建主题和观察者
subject = Subject()
observer1 = Observer("观察者1")
observer2 = Observer("观察者2")

# 添加观察者
subject.attach(observer1)
subject.attach(observer2)

# 通知观察者
subject.notify("你好,世界!")
# 观察者1 收到消息: 你好,世界!
# 观察者2 收到消息: 你好,世界!

# 移除观察者
subject.detach(observer1)
subject.notify("再见!")
# 观察者2 收到消息: 再见!

实际项目应用:小型代码管理系统

让我们将所学知识应用到一个小型的代码版本管理系统:

from datetime import datetime
import uuid

class CodeFile:
    def __init__(self, name, content=""):
        self.name = name
        self.content = content
        self.created_at = datetime.now()
        self.updated_at = self.created_at
    
    def update_content(self, content):
        self.content = content
        self.updated_at = datetime.now()
    
    def __str__(self):
        return f"文件: {self.name}, 最后更新: {self.updated_at}"

class Commit:
    def __init__(self, message, author):
        self.id = str(uuid.uuid4())[:8]  # 生成短UUID
        self.message = message
        self.author = author
        self.timestamp = datetime.now()
        self.files = {}  # 文件快照
    
    def add_file(self, file):
        # 创建文件的快照 (深拷贝)
        snapshot = CodeFile(file.name, file.content)
        self.files[file.name] = snapshot
    
    def __str__(self):
        return f"提交 {self.id}: {self.message} by {self.author} at {self.timestamp}"

class Repository:
    def __init__(self, name):
        self.name = name
        self.files = {}     # 当前工作区文件
        self.commits = []   # 提交历史
    
    def create_file(self, name, content=""):
        if name in self.files:
            raise ValueError(f"文件 {name} 已存在")
        self.files[name] = CodeFile(name, content)
        return self.files[name]
    
    def update_file(self, name, content):
        if name not in self.files:
            raise ValueError(f"文件 {name} 不存在")
        self.files[name].update_content(content)
        return self.files[name]
    
    def commit(self, message, author):
        commit = Commit(message, author)
        for file in self.files.values():
            commit.add_file(file)
        self.commits.append(commit)
        return commit
    
    def get_file_history(self, file_name):
        history = []
        for commit in self.commits:
            if file_name in commit.files:
                history.append({
                    'commit': commit,
                    'content': commit.files[file_name].content
                })
        return history
    
    def __str__(self):
        return f"仓库: {self.name}, 文件数: {len(self.files)}, 提交数: {len(self.commits)}"

# 使用示例
repo = Repository("我的项目")

# 创建文件
hello_py = repo.create_file("hello.py", "print('Hello, World!')")
readme = repo.create_file("README.md", "# 我的项目\n这是一个示例项目。")

# 提交
repo.commit("初始提交", "张三")

# 更新文件
repo.update_file("hello.py", "print('Hello, Python!')\nprint('Welcome to OOP!')")
repo.commit("更新 hello.py", "张三")

# 查看仓库信息
print(repo)  # 仓库: 我的项目, 文件数: 2, 提交数: 2

# 查看文件历史
history = repo.get_file_history("hello.py")
for entry in history:
    print(f"{entry['commit'].id}: {entry['content']}")

总结

面向对象编程是Python强大的编程范式之一,通过类和对象的概念,可以将复杂问题分解为易于管理的部分。关键点包括:

  1. 类与对象:类是定义,对象是实例
  2. 四大支柱:封装、继承、多态、抽象
  3. 特殊方法:使类更"Pythonic"
  4. 属性装饰器:方法伪装成属性
  5. 类方法与静态方法:超越实例的功能
  6. 组合与继承:代码复用的两种方式
  7. 设计模式:解决常见问题的模式

掌握这些概念后,你就可以设计出结构清晰、易于维护的代码,为更高级的Python应用打下坚实基础!

练习

  1. 创建一个动物园系统

    • Implement a Zoo class that manages different animal classes
    • Practice inheritance and polymorphism
  2. 实现一个简单的银行系统

    • Account classes with different types
    • Transaction tracking and account management
  3. 开发一个命令行游戏

    • Use classes for game objects and states
    • Practice encapsulation and abstraction
  4. 创建一个自定义容器类

    • Implement special methods like __getitem__, __setitem__, etc.
    • Make your container behave like a list or dictionary

记住,理解概念很重要,但真正掌握面向对象编程需要大量实践。从简单的项目开始,逐步挑战更复杂的问题!

1. 创建一个动物园系统

# 动物园系统实现

class Animal:
    """动物基类"""
    def __init__(self, name, age, health=100, hunger=0):
        self.name = name
        self.age = age
        self.health = health
        self.hunger = hunger
        
    def make_sound(self):
        """动物发出声音"""
        pass
    
    def eat(self, food_amount):
        """动物进食"""
        self.hunger = max(0, self.hunger - food_amount)
        print(f"{self.name} has eaten. Hunger level: {self.hunger}")
        
    def update_status(self):
        """更新动物状态"""
        self.hunger += 10
        if self.hunger > 100:
            self.health -= 10
            print(f"{self.name} is too hungry and losing health!")
        
    def __str__(self):
        return f"{self.__class__.__name__}: {self.name}, Age: {self.age}, Health: {self.health}, Hunger: {self.hunger}"


class Mammal(Animal):
    """哺乳动物类"""
    def __init__(self, name, age, fur_color, health=100, hunger=0):
        super().__init__(name, age, health, hunger)
        self.fur_color = fur_color
        
    def give_birth(self):
        """哺乳动物生育"""
        print(f"{self.name} has given birth to a baby!")


class Bird(Animal):
    """鸟类"""
    def __init__(self, name, age, wing_span, health=100, hunger=0):
        super().__init__(name, age, health, hunger)
        self.wing_span = wing_span
        
    def fly(self):
        """鸟类飞行"""
        print(f"{self.name} is flying with a wingspan of {self.wing_span}cm!")


class Lion(Mammal):
    """狮子类"""
    def make_sound(self):
        return "ROAR!"
    
    def hunt(self):
        """狮子捕猎"""
        self.hunger = max(0, self.hunger - 30)
        print(f"{self.name} has hunted successfully. Hunger decreased to {self.hunger}")


class Parrot(Bird):
    """鹦鹉类"""
    def __init__(self, name, age, wing_span, vocabulary=None, health=100, hunger=0):
        super().__init__(name, age, wing_span, health, hunger)
        self.vocabulary = vocabulary or []
        
    def make_sound(self):
        return "Squawk!"
    
    def talk(self):
        """鹦鹉说话"""
        if not self.vocabulary:
            return f"{self.name} doesn't know any words yet."
        return f"{self.name} says: {self.vocabulary[0]}"
    
    def learn_word(self, word):
        """鹦鹉学习新词"""
        self.vocabulary.append(word)
        print(f"{self.name} learned a new word: {word}")


class Zoo:
    """动物园类"""
    def __init__(self, name):
        self.name = name
        self.animals = {}
        self.animal_count = 0
        
    def add_animal(self, animal):
        """添加动物到动物园"""
        self.animal_count += 1
        animal_id = self.animal_count
        self.animals[animal_id] = animal
        print(f"{animal.name} has been added to {self.name} Zoo with ID: {animal_id}")
        return animal_id
        
    def remove_animal(self, animal_id):
        """从动物园移除动物"""
        if animal_id in self.animals:
            animal = self.animals.pop(animal_id)
            print(f"{animal.name} has been removed from {self.name} Zoo")
            return True
        return False
    
    def feed_animal(self, animal_id, food_amount):
        """喂养动物"""
        if animal_id in self.animals:
            self.animals[animal_id].eat(food_amount)
            return True
        return False
    
    def update_all_animals(self):
        """更新所有动物状态"""
        print(f"Updating all animals in {self.name} Zoo...")
        for animal in self.animals.values():
            animal.update_status()
    
    def get_animal_sounds(self):
        """获取所有动物的声音"""
        sounds = {}
        for animal_id, animal in self.animals.items():
            sounds[animal_id] = animal.make_sound()
        return sounds
    
    def __str__(self):
        result = f"{self.name} Zoo with {len(self.animals)} animals:\n"
        for animal_id, animal in self.animals.items():
            result += f"ID {animal_id}: {animal}\n"
        return result


# 测试代码
if __name__ == "__main__":
    # 创建动物园
    central_zoo = Zoo("Central")
    
    # 创建动物
    simba = Lion("Simba", 5, "Golden", health=95, hunger=20)
    nala = Lion("Nala", 4, "Tan")
    polly = Parrot("Polly", 2, 30, ["Hello", "Goodbye"])
    
    # 添加动物到动物园
    simba_id = central_zoo.add_animal(simba)
    nala_id = central_zoo.add_animal(nala)
    polly_id = central_zoo.add_animal(polly)
    
    # 测试动物行为
    print(simba.make_sound())  # ROAR!
    simba.hunt()  # 狮子捕猎
    
    polly.learn_word("I'm hungry!")  # 鹦鹉学习新词
    print(polly.talk())  # 鹦鹉说话
    
    # 喂养动物
    central_zoo.feed_animal(nala_id, 30)
    
    # 更新所有动物状态
    central_zoo.update_all_animals()
    
    # 打印动物园信息
    print(central_zoo)
    
    # 获取所有动物的声音
    sounds = central_zoo.get_animal_sounds()
    for animal_id, sound in sounds.items():
        animal = central_zoo.animals[animal_id]
        print(f"Animal ID {animal_id} ({animal.name}) says: {sound}")

2.实现一个简单的银行系统

# 银行系统实现

import datetime
from abc import ABC, abstractmethod
import uuid

class Transaction:
    """交易类"""
    def __init__(self, amount, description, transaction_type):
        self.transaction_id = str(uuid.uuid4())[:8]  # 生成唯一交易ID
        self.amount = amount
        self.description = description
        self.timestamp = datetime.datetime.now()
        self.transaction_type = transaction_type  # "deposit", "withdrawal", "transfer"
        
    def __str__(self):
        return f"[{self.timestamp.strftime('%Y-%m-%d %H:%M:%S')}] {self.transaction_type.upper()}: {self.amount:.2f} - {self.description} (ID: {self.transaction_id})"


class Account(ABC):
    """账户抽象基类"""
    def __init__(self, account_number, owner_name, balance=0):
        self.account_number = account_number
        self.owner_name = owner_name
        self._balance = balance
        self.transactions = []
        
    @property
    def balance(self):
        """获取账户余额"""
        return self._balance
    
    def deposit(self, amount, description="Deposit"):
        """存款"""
        if amount <= 0:
            raise ValueError("Deposit amount must be positive")
        
        self._balance += amount
        transaction = Transaction(amount, description, "deposit")
        self.transactions.append(transaction)
        return transaction
    
    def withdraw(self, amount, description="Withdrawal"):
        """取款"""
        if amount <= 0:
            raise ValueError("Withdrawal amount must be positive")
        
        if amount > self._balance:
            raise ValueError("Insufficient funds")
        
        self._balance -= amount
        transaction = Transaction(amount, description, "withdrawal")
        self.transactions.append(transaction)
        return transaction
    
    def get_transaction_history(self):
        """获取交易历史"""
        return self.transactions
    
    @abstractmethod
    def get_account_type(self):
        """获取账户类型"""
        pass
    
    def __str__(self):
        return f"{self.get_account_type()} - {self.account_number} ({self.owner_name}): ${self.balance:.2f}"


class SavingsAccount(Account):
    """储蓄账户类"""
    def __init__(self, account_number, owner_name, balance=0, interest_rate=0.01):
        super().__init__(account_number, owner_name, balance)
        self.interest_rate = interest_rate
        
    def apply_interest(self):
        """应用利息"""
        interest = self._balance * self.interest_rate
        self.deposit(interest, "Interest applied")
        return interest
    
    def get_account_type(self):
        return "Savings Account"


class CheckingAccount(Account):
    """支票账户类"""
    def __init__(self, account_number, owner_name, balance=0, overdraft_limit=100):
        super().__init__(account_number, owner_name, balance)
        self.overdraft_limit = overdraft_limit
        
    def withdraw(self, amount, description="Withdrawal"):
        """支票账户取款,支持透支"""
        if amount <= 0:
            raise ValueError("Withdrawal amount must be positive")
        
        if amount > (self._balance + self.overdraft_limit):
            raise ValueError(f"Withdrawal exceeds overdraft limit. Maximum withdrawal: ${self._balance + self.overdraft_limit:.2f}")
        
        self._balance -= amount
        transaction = Transaction(amount, description, "withdrawal")
        self.transactions.append(transaction)
        
        if self._balance < 0:
            print(f"Warning: Account {self.account_number} is overdrawn by ${abs(self._balance):.2f}")
            
        return transaction
    
    def get_account_type(self):
        return "Checking Account"


class Bank:
    """银行类"""
    def __init__(self, name):
        self.name = name
        self.accounts = {}
        self.next_account_number = 10000  # 起始账号
        
    def create_account(self, owner_name, account_type, initial_deposit=0, **kwargs):
        """创建新账户"""
        account_number = str(self.next_account_number)
        self.next_account_number += 1
        
        if account_type.lower() == "savings":
            interest_rate = kwargs.get("interest_rate", 0.01)
            account = SavingsAccount(account_number, owner_name, initial_deposit, interest_rate)
        elif account_type.lower() == "checking":
            overdraft_limit = kwargs.get("overdraft_limit", 100)
            account = CheckingAccount(account_number, owner_name, initial_deposit, overdraft_limit)
        else:
            raise ValueError("Invalid account type")
        
        self.accounts[account_number] = account
        
        if initial_deposit > 0:
            account.deposit(initial_deposit, "Initial deposit")
        
        print(f"Account created: {account}")
        return account
    
    def get_account(self, account_number):
        """获取账户"""
        if account_number not in self.accounts:
            raise ValueError("Account not found")
        return self.accounts[account_number]
    
    def transfer(self, from_account_number, to_account_number, amount, description="Transfer"):
        """账户间转账"""
        if amount <= 0:
            raise ValueError("Transfer amount must be positive")
        
        from_account = self.get_account(from_account_number)
        to_account = self.get_account(to_account_number)
        
        # 从源账户取款
        from_transaction = from_account.withdraw(amount, f"Transfer to account {to_account_number}: {description}")
        
        # 存入目标账户
        to_transaction = to_account.deposit(amount, f"Transfer from account {from_account_number}: {description}")
        
        return (from_transaction, to_transaction)
    
    def apply_interest_to_all_savings(self):
        """为所有储蓄账户应用利息"""
        applied_count = 0
        total_interest = 0
        
        for account in self.accounts.values():
            if isinstance(account, SavingsAccount):
                interest = account.apply_interest()
                total_interest += interest
                applied_count += 1
                
        print(f"Applied interest to {applied_count} accounts. Total interest: ${total_interest:.2f}")
        return total_interest
    
    def get_total_deposits(self):
        """获取所有账户的总存款额"""
        return sum(account.balance for account in self.accounts.values())
    
    def __str__(self):
        return f"{self.name} Bank - {len(self.accounts)} accounts, Total deposits: ${self.get_total_deposits():.2f}"


# 测试代码
if __name__ == "__main__":
    # 创建银行
    chase_bank = Bank("Chase")
    
    # 创建账户
    john_savings = chase_bank.create_account("John Smith", "savings", 1000, interest_rate=0.02)
    john_checking = chase_bank.create_account("John Smith", "checking", 500, overdraft_limit=200)
    alice_savings = chase_bank.create_account("Alice Johnson", "savings", 2500)
    
    # 测试存款和取款
    john_savings.deposit(500, "Salary deposit")
    john_checking.withdraw(200, "ATM withdrawal")
    
    try:
        john_checking.withdraw(1000, "Large purchase")
    except ValueError as e:
        print(f"Error: {e}")
    
    # 测试转账
    chase_bank.transfer(john_savings.account_number, alice_savings.account_number, 300, "Debt repayment")
    
    # 应用利息
    chase_bank.apply_interest_to_all_savings()
    
    # 打印账户信息
    print("\nAccount Information:")
    for account in chase_bank.accounts.values():
        print(account)
    
    # 打印交易历史
    print("\nTransaction History for John's Savings Account:")
    for transaction in john_savings.get_transaction_history():
        print(transaction)
    
    # 打印银行信息
    print("\nBank Information:")
    print(chase_bank)

3.开发一个命令行游戏

# 命令行冒险游戏实现

import random
import time
import sys
from enum import Enum, auto

class GameState(Enum):
    """游戏状态枚举"""
    MAIN_MENU = auto()
    PLAYING = auto()
    BATTLE = auto()
    SHOP = auto()
    INVENTORY = auto()
    GAME_OVER = auto()
    VICTORY = auto()
    QUIT = auto()


class Item:
    """物品基类"""
    def __init__(self, name, description, value):
        self.name = name
        self.description = description
        self.value = value
        
    def __str__(self):
        return f"{self.name} - {self.description} (Value: {self.value} gold)"


class Weapon(Item):
    """武器类"""
    def __init__(self, name, description, value, damage):
        super().__init__(name, description, value)
        self.damage = damage
        
    def __str__(self):
        return f"{self.name} - {self.description} (Damage: {self.damage}, Value: {self.value} gold)"


class Potion(Item):
    """药水类"""
    def __init__(self, name, description, value, heal_amount):
        super().__init__(name, description, value)
        self.heal_amount = heal_amount
        
    def __str__(self):
        return f"{self.name} - {self.description} (Heals: {self.heal_amount} HP, Value: {self.value} gold)"


class Armor(Item):
    """护甲类"""
    def __init__(self, name, description, value, defense):
        super().__init__(name, description, value)
        self.defense = defense
        
    def __str__(self):
        return f"{self.name} - {self.description} (Defense: {self.defense}, Value: {self.value} gold)"


class Character:
    """角色基类"""
    def __init__(self, name, hp, attack_power):
        self.name = name
        self.max_hp = hp
        self.hp = hp
        self.base_attack = attack_power
        
    def is_alive(self):
        """检查角色是否存活"""
        return self.hp > 0
    
    def take_damage(self, damage):
        """受到伤害"""
        self.hp = max(0, self.hp - damage)
        return damage
    
    def heal(self, amount):
        """恢复生命值"""
        self.hp = min(self.max_hp, self.hp + amount)
        return amount
    
    def attack(self, target):
        """攻击目标"""
        damage = self.base_attack
        return target.take_damage(damage)


class Player(Character):
    """玩家类"""
    def __init__(self, name, hp=100, attack_power=10):
        super().__init__(name, hp, attack_power)
        self.inventory = []
        self.gold = 50
        self.weapon = None
        self.armor = None
        self.level = 1
        self.exp = 0
        self.exp_to_level = 100
        
    def attack(self, target):
        """玩家攻击,考虑武器伤害"""
        damage = self.base_attack
        if self.weapon:
            damage += self.weapon.damage
        return target.take_damage(damage)
    
    def take_damage(self, damage):
        """玩家受到伤害,考虑护甲防御"""
        if self.armor:
            damage = max(1, damage - self.armor.defense)  # 至少造成1点伤害
        return super().take_damage(damage)
    
    def add_item(self, item):
        """添加物品到库存"""
        self.inventory.append(item)
        print(f"Added {item.name} to your inventory.")
    
    def remove_item(self, item):
        """从库存移除物品"""
        if item in self.inventory:
            self.inventory.remove(item)
            return True
        return False
    
    def equip_weapon(self, weapon_index):
        """装备武器"""
        if 0 <= weapon_index < len(self.inventory):
            item = self.inventory[weapon_index]
            if isinstance(item, Weapon):
                old_weapon = self.weapon
                self.weapon = item
                if old_weapon:
                    print(f"Unequipped {old_weapon.name} and equipped {item.name}.")
                else:
                    print(f"Equipped {item.name}.")
                return True
        return False
    
    def equip_armor(self, armor_index):
        """装备护甲"""
        if 0 <= armor_index < len(self.inventory):
            item = self.inventory[armor_index]
            if isinstance(item, Armor):
                old_armor = self.armor
                self.armor = item
                if old_armor:
                    print(f"Unequipped {old_armor.name} and equipped {item.name}.")
                else:
                    print(f"Equipped {item.name}.")
                return True
        return False
    
    def use_potion(self, potion_index):
        """使用药水"""
        if 0 <= potion_index < len(self.inventory):
            item = self.inventory[potion_index]
            if isinstance(item, Potion):
                healed = self.heal(item.heal_amount)
                print(f"Used {item.name} and healed for {healed} HP.")
                self.remove_item(item)
                return True
        return False
    
    def add_exp(self, amount):
        """增加经验值"""
        self.exp += amount
        print(f"Gained {amount} experience points!")
        
        # 检查是否升级
        while self.exp >= self.exp_to_level:
            self.level_up()
    
    def level_up(self):
        """升级"""
        self.exp -= self.exp_to_level
        self.level += 1
        self.max_hp += 20
        self.hp = self.max_hp
        self.base_attack += 5
        self.exp_to_level = int(self.exp_to_level * 1.5)
        print(f"\n*** LEVEL UP! ***\nYou are now level {self.level}!")
        print(f"Max HP increased to {self.max_hp}")
        print(f"Attack increased to {self.base_attack}")
    
    def __str__(self):
        equipped = []
        if self.weapon:
            equipped.append(f"Weapon: {self.weapon.name} (+{self.weapon.damage} damage)")
        if self.armor:
            equipped.append(f"Armor: {self.armor.name} (+{self.armor.defense} defense)")
            
        return (
            f"{self.name} (Level {self.level})\n"
            f"HP: {self.hp}/{self.max_hp} | Gold: {self.gold} | EXP: {self.exp}/{self.exp_to_level}\n"
            f"Attack: {self.base_attack}{' + ' + str(self.weapon.damage) if self.weapon else ''}\n"
            f"Defense: {self.armor.defense if self.armor else 0}\n"
            f"Equipped: {', '.join(equipped) if equipped else 'Nothing'}"
        )


class Enemy(Character):
    """敌人类"""
    def __init__(self, name, hp, attack_power, gold_reward, exp_reward):
        super().__init__(name, hp, attack_power)
        self.gold_reward = gold_reward
        self.exp_reward = exp_reward
        
    def __str__(self):
        return f"{self.name} (HP: {self.hp}/{self.max_hp}, Attack: {self.base_attack})"


class Shop:
    """商店类"""
    def __init__(self):
        self.inventory = []
        self.initialize_inventory()
        
    def initialize_inventory(self):
        """初始化商店库存"""
        # 武器
        self.inventory.append(Weapon("Dagger", "A small but sharp dagger", 25, 5))
        self.inventory.append(Weapon("Sword", "A standard iron sword", 60, 10))
        self.inventory.append(Weapon("Battle Axe", "A heavy battle axe", 120, 20))
        
        # 护甲
        self.inventory.append(Armor("Leather Armor", "Basic protection made of leather", 40, 5))
        self.inventory.append(Armor("Chain Mail", "Medium armor made of interlocking rings", 100, 10))
        self.inventory.append(Armor("Plate Armor", "Heavy armor offering excellent protection", 200, 20))
        
        # 药水
        self.inventory.append(Potion("Minor Healing Potion", "Restores a small amount of health", 15, 20))
        self.inventory.append(Potion("Healing Potion", "Restores a moderate amount of health", 30, 50))
        self.inventory.append(Potion("Major Healing Potion", "Restores a large amount of health", 60, 100))
    
    def buy_item(self, player, item_index):
        """玩家购买物品"""
        if 0 <= item_index < len(self.inventory):
            item = self.inventory[item_index]
            if player.gold >= item.value:
                player.gold -= item.value
                player.add_item(item)
                print(f"You bought {item.name} for {item.value} gold.")
                return True
            else:
                print("You don't have enough gold!")
        return False
    
    def sell_item(self, player, item_index):
        """玩家出售物品"""
        if 0 <= item_index < len(player.inventory):
            item = player.inventory[item_index]
            sell_value = item.value // 2  # 卖出价为原价的一半
            
            # 确保未装备的物品才能出售
            if item == player.weapon or item == player.armor:
                print("You cannot sell equipped items!")
                return False
            
            player.gold += sell_value
            player.remove_item(item)
            print(f"You sold {item.name} for {sell_value} gold.")
            return True
        return False


class Game:
    """游戏主类"""
    def __init__(self):
        self.state = GameState.MAIN_MENU
        self.player = None
        self.current_enemy = None
        self.shop = Shop()
        self.enemy_types = [
            {"name": "Goblin", "hp": 30, "attack": 5, "gold": 10, "exp": 20},
            {"name": "Orc", "hp": 50, "attack": 8, "gold": 15, "exp": 30},
            {"name": "Troll", "hp": 80, "attack": 12, "gold": 25, "exp": 50},
            {"name": "Dragon", "hp": 200, "attack": 20, "gold": 100, "exp": 200}
        ]
    
    def clear_screen(self):
        """清屏"""
        print("\n" * 50)
    
    def slow_print(self, text, delay=0.03):
        """缓慢打印文本,增强游戏体验"""
        for char in text:
            print(char, end='', flush=True)
            time.sleep(delay)
        print()
    
    def print_header(self, title):
        """打印标题栏"""
        print("\n" + "=" * 60)
        print(f"{title:^60}")
        print("=" * 60 + "\n")
    
    def wait_for_input(self):
        """等待用户按任意键继续"""
        input("\nPress Enter to continue...")
    
    def show_main_menu(self):
        """显示主菜单"""
        self.clear_screen()
        self.print_header("DUNGEON ADVENTURE")
        self.slow_print("Welcome to Dungeon Adventure!", 0.05)
        print("\n1. New Game")
        print("2. Quit\n")
        
        choice = input("Enter your choice (1-2): ")
        if choice == "1":
            self.start_new_game()
        elif choice == "2":
            self.state = GameState.QUIT
        else:
            print("Invalid choice. Please try again.")
            self.wait_for_input()
    
    def start_new_game(self):
        """开始新游戏"""
        self.clear_screen()
        self.print_header("CHARACTER CREATION")
        
        name = input("Enter your hero's name: ")
        if not name:
            name = "Hero"
        
        self.player = Player(name)
        
        # 给予玩家初始装备
        starter_weapon = Weapon("Rusty Sword", "An old sword with some rust spots", 0, 3)
        self.player.add_item(starter_weapon)
        self.player.equip_weapon(0)
        
        starter_potion = Potion("Small Health Potion", "A tiny vial of red liquid", 0, 15)
        self.player.add_item(starter_potion)
        
        self.slow_print(f"\nWelcome, {self.player.name}! Your adventure begins...", 0.05)
        self.slow_print("You find yourself at the entrance of a dark dungeon.", 0.05)
        self.slow_print("Legends say it's filled with monsters and treasures.", 0.05)
        self.slow_print("Are you brave enough to explore it?", 0.05)
        
        self.wait_for_input()
        self.state = GameState.PLAYING
    
    def show_game_menu(self):
        """显示游戏主菜单"""
        self.clear_screen()
        self.print_header("DUNGEON ADVENTURE")
        
        print(self.player)
        print("\nWhat would you like to do?")
        print("1. Explore the dungeon")
        print("2. Visit the shop")
        print("3. Check inventory")
        print("4. Rest (Heal 20% HP)")
        print("5. Quit to main menu\n")
        
        choice = input("Enter your choice (1-5): ")
        if choice == "1":
            self.explore()
        elif choice == "2":
            self.state = GameState.SHOP
        elif choice == "3":
            self.state = GameState.INVENTORY
        elif choice == "4":
            self.rest()
        elif choice == "5":
            self.state = GameState.MAIN_MENU
        else:
            print("Invalid choice. Please try again.")
            self.wait_for_input()
    
    def explore(self):
        """探索地牢"""
        self.clear_screen()
        self.print_header("EXPLORING THE DUNGEON")
        
        self.slow_print("You venture deeper into the dungeon...", 0.05)
        time.sleep(1)
        
        # 随机事件: 战斗、发现物品、或者什么都没发生
        event = random.randint(1, 10)
        
        if event <= 7:  # 70% 概率遇到敌人
            self.encounter_enemy()
        elif event <= 9:  # 20% 概率发现物品
            self.find_item()
        else:  # 10% 概率什么都没发生
            self.slow_print("You explore for a while but find nothing of interest.")
            self.wait_for_input()
    
    def encounter_enemy(self):
        """遇到敌人"""
        # 根据玩家等级选择合适的敌人
        enemy_level = min(len(self.enemy_types) - 1, self.player.level - 1)
        enemy_type = self.enemy_types[random.randint(0, enemy_level)]
        
        # 根据玩家等级调整敌人属性
        hp_modifier = 1.0 + (self.player.level - 1) * 0.2
        attack_modifier = 1.0 + (self.player.level - 1) * 0.1
        reward_modifier = 1.0 + (self.player.level - 1) * 0.3
        
        self.current_enemy = Enemy(
            enemy_type["name"],
            int(enemy_type["hp"] * hp_modifier),
            int(enemy_type["attack"] * attack_modifier),
            int(enemy_type["gold"] * reward_modifier),
            int(enemy_type["exp"] * reward_modifier)
        )
        
        self.slow_print(f"You encountered a {self.current_enemy.name}!")
        self.state = GameState.BATTLE
    
    def find_item(self):
        """发现物品"""
        item_type = random.randint(1, 3)
        
        if item_type == 1:  # 发现金币
            gold_amount = random.randint(5, 15) * self.player.level
            self.player.gold += gold_amount
            self.slow_print(f"You found a small pouch containing {gold_amount} gold coins!")
        
        elif item_type == 2:  # 发现药水
            potion_power = random.randint(1, 3)
            if potion_power == 1:
                potion = Potion("Minor Healing Potion", "Restores a small amount of health", 15, 20)
            elif potion_power == 2:
                potion = Potion("Healing Potion", "Restores a moderate amount of health", 30, 50)
            else:
                potion = Potion("Major Healing Potion", "Restores a large amount of health", 60, 100)
                
            self.player.add_item(potion)
            self.slow_print(f"You found a {potion.name}!")
        
        else:  # 发现装备
            equipment_type = random.randint(1, 2)
            equipment_quality = random.randint(1, 3) * self.player.level
            
            if equipment_type == 1:  # 武器
                weapon_types = ["Dagger", "Sword", "Axe", "Mace", "Spear"]
                weapon_name = f"{random.choice(['Rusty', 'Iron', 'Steel', 'Silver', 'Enchanted'])} {random.choice(weapon_types)}"
                weapon = Weapon(weapon_name, f"A {weapon_name.lower()} found in the dungeon", equipment_quality * 10, equipment_quality * 2)
                self.player.add_item(weapon)
                self.slow_print(f"You found a {weapon.name}!")
            
            else:  # 护甲
                armor_types = ["Armor", "Shield", "Helmet", "Gauntlets", "Boots"]
                armor_name = f"{random.choice(['Leather', 'Chain', 'Plate', 'Reinforced', 'Magical'])} {random.choice(armor_types)}"
                armor = Armor(armor_name, f"A {armor_name.lower()} found in the dungeon", equipment_quality * 15, equipment_quality)
                self.player.add_item(armor)
                self.slow_print(f"You found a {armor.name}!")
        
        self.wait_for_input()
    
    def battle(self):
        """战斗系统"""
        self.clear_screen()
        self.print_header("BATTLE")
        
        print(f"{self.player.name}: {self.player.hp}/{self.player.max_hp} HP")
        print(f"{self.current_enemy.name}: {self.current_enemy.hp}/{self.current_enemy.max_hp} HP\n")
        
        print("What will you do?")
        print("1. Attack")
        print("2. Use Potion")
        print("3. Run Away\n")
        
        choice = input("Enter your choice (1-3): ")
        
        if choice == "1":  # 攻击
            self.player_attack()
        elif choice == "2":  # 使用药水
            self.use_potion_in_battle()
        elif choice == "3":  # 逃跑
            if random.random() < 0.7:  # 70% 成功率
                self.slow_print("You successfully escaped!")
                self.state = GameState.PLAYING
                self.wait_for_input()
            else:
                self.slow_print("You failed to escape!")
                self.enemy_attack()
        else:
            print("Invalid choice. Please try again.")
            self.wait_for_input()
    
    def player_attack(self):
        """玩家攻击"""
        damage = self.player.attack(self.current_enemy)
        self.slow_print(f"You attacked the {self.current_enemy.name} and dealt {damage} damage!")
        
        if not self.current_enemy.is_alive():
            self.battle_victory()
        else:
            self.enemy_attack()
    
    def enemy_attack(self):
        """敌人攻击"""
        damage = self.current_enemy.attack(self.player)
        self.slow_print(f"The {self.current_enemy.name} attacked you and dealt {damage} damage!")
        
        if not self.player.is_alive():
            self.game_over()
        else:
            self.wait_for_input()
    
    def use_potion_in_battle(self):
        """在战斗中使用药水"""
        potions = [(i, item) for i, item in enumerate(self.player.inventory) if isinstance(item, Potion)]
        
        if not potions:
            self.slow_print("You don't have any potions!")
            self.enemy_attack()
            return
        
        print("\nAvailable Potions:")
        for i, (idx, potion) in enumerate(potions):
            print(f"{i+1}. {potion.name} (+{potion.heal_amount} HP)")
        print(f"{len(potions)+1}. Cancel")
        
        try:
            choice = int(input(f"\nSelect a potion (1-{len(potions)+1}): "))
            if 1 <= choice <= len(potions):
                idx = potions[choice-1][0]
                if self.player.use_potion(idx):
                    # 使用药水后敌人仍然会攻击
                    self.enemy_attack()
            elif choice == len(potions)+1:
                # 取消使用药水
                self.battle()
            else:
                print("Invalid choice.")
                self.use_potion_in_battle()
        except ValueError:
            print("Please enter a valid number.")
            self.use_potion_in_battle()
    
    def battle_victory(self):
        """战斗胜利"""
        self.clear_screen()
        self.print_header("VICTORY")
        
        self.slow_print(f"You defeated the {self.current_enemy.name}!")
        
        # 奖励
        gold_reward = self.current_enemy.gold_reward
        exp_reward = self.current_enemy.exp_reward
        
        self.player.gold += gold_reward
        self.slow_print(f"You gained {gold_reward} gold!")
        
        self.player.add_exp(exp_reward)
        
        # 小概率额外奖励
        if random.random() < 0.3:  # 30% 概率获得物品
            self.find_item()
        
        self.current_enemy = None
        self.state = GameState.PLAYING
        self.wait_for_input()
    
    def game_over(self):
        """游戏结束"""
        self.clear_screen()
        self.print_header("GAME OVER")
        
        self.slow_print("You have been defeated...", 0.1)
        self.slow_print(f"\nFinal Stats:")
        self.slow_print(f"Level: {self.player.level}")
        self.slow_print(f"Gold collected: {self.player.gold}")
        
        self.wait_for_input()
        self.state = GameState.MAIN_MENU
    
    def rest(self):
        """休息恢复生命值"""
        if self.player.hp == self.player.max_hp:
            self.slow_print("You are already at full health!")
        else:
            heal_amount = int(self.player.max_hp * 0.2)  # 恢复20%最大生命值
            actual_heal = self.player.heal(heal_amount)
            self.slow_print(f"You rest for a while and recover {actual_heal} HP.")
        
        self.wait_for_input()
    
    def show_shop(self):
        """显示商店界面"""
        self.clear_screen()
        self.print_header("SHOP")
        
        print(f"Your gold: {self.player.gold}\n")
        print("Available Items:")
        
        for i, item in enumerate(self.shop.inventory):
            print(f"{i+1}. {item} - {item.value} gold")
        
        print(f"\n{len(self.shop.inventory)+1}. Sell items")
        print(f"{len(self.shop.inventory)+2}. Back to main menu")
        
        try:
            choice = int(input(f"\nEnter your choice (1-{len(self.shop.inventory)+2}): "))
            
            if 1 <= choice <= len(self.shop.inventory):
                self.shop.buy_item(self.player, choice-1)
                self.wait_for_input()
                
            elif choice == len(self.shop.inventory)+1:
                self.sell_items()
                
            elif choice == len(self.shop.inventory)+2:
                self.state = GameState.PLAYING
                
            else:
                print("Invalid choice. Please try again.")
                self.wait_for_input()
                
        except ValueError:
            print("Please enter a valid number.")
            self.wait_for_input()
    
    def sell_items(self):
        """出售物品界面"""
        self.clear_screen()
        self.print_header("SELL ITEMS")
        
        if not self.player.inventory:
            self.slow_print("You don't have any items to sell!")
            self.wait_for_input()
            return
        
        print(f"Your gold: {self.player.gold}\n")
        print("Your Items:")
        
        for i, item in enumerate(self.player.inventory):
            equipped = ""
            if item == self.player.weapon:
                equipped = " [Equipped Weapon]"
            elif item == self.player.armor:
                equipped = " [Equipped Armor]"
                
            sell_value = item.value // 2
            print(f"{i+1}. {item} - Sell for {sell_value} gold{equipped}")
        
        print(f"\n{len(self.player.inventory)+1}. Back to shop")
        
        try:
            choice = int(input(f"\nEnter your choice (1-{len(self.player.inventory)+1}): "))
            
            if 1 <= choice <= len(self.player.inventory):
                self.shop.sell_item(self.player, choice-1)
                self.wait_for_input()
                self.sell_items()  # 返回出售界面
                
            elif choice == len(self.player.inventory)+1:
                return  # 返回商店
                
            else:
                print("Invalid choice. Please try again.")
                self.wait_for_input()
                self.sell_items()
                
        except ValueError:
            print("Please enter a valid number.")
            self.wait_for_input()
            self.sell_items()
    
    def show_inventory(self):
        """显示库存界面"""
        self.clear_screen()
        self.print_header("INVENTORY")
        
        if not self.player.inventory:
            self.slow_print("Your inventory is empty!")
            self.wait_for_input()
            self.state = GameState.PLAYING
            return
        
        print(f"Gold: {self.player.gold}\n")
        print("Items:")
        
        weapons = []
        armors = []
        potions = []
        
        for i, item in enumerate(self.player.inventory):
            equipped = ""
            if item == self.player.weapon:
                equipped = " [Equipped]"
                weapons.append((i, item, equipped))
            elif item == self.player.armor:
                equipped = " [Equipped]"
                armors.append((i, item, equipped))
            elif isinstance(item, Weapon):
                weapons.append((i, item, equipped))
            elif isinstance(item, Armor):
                armors.append((i, item, equipped))
            elif isinstance(item, Potion):
                potions.append((i, item, equipped))
        
        if weapons:
            print("\nWeapons:")
            for i, item, equipped in weapons:
                print(f"{i+1}. {item}{equipped}")
        
        if armors:
            print("\nArmors:")
            for i, item, equipped in armors:
                print(f"{i+1}. {item}{equipped}")
        
        if potions:
            print("\nPotions:")
            for i, item, equipped in potions:
                print(f"{i+1}. {item}")
        
        print(f"\nActions:")
        print(f"e. Equip item")
        print(f"u. Use item")
        print(f"b. Back to main menu")
        
        choice = input("\nEnter your choice: ").lower()
        
        if choice == 'e':
            self.equip_item()
        elif choice == 'u':
            self.use_item()
        elif choice == 'b':
            self.state = GameState.PLAYING
        else:
            print("Invalid choice. Please try again.")
            self.wait_for_input()
    
    def equip_item(self):
        """装备物品界面"""
        self.clear_screen()
        self.print_header("EQUIP ITEM")
        
        equipment = [(i, item) for i, item in enumerate(self.player.inventory) 
                    if isinstance(item, Weapon) or isinstance(item, Armor)]
        
        if not equipment:
            self.slow_print("You don't have any equipment to equip!")
            self.wait_for_input()
            return
        
        print("Available Equipment:")
        for i, (idx, item) in enumerate(equipment):
            equipped = ""
            if item == self.player.weapon or item == self.player.armor:
                equipped = " [Equipped]"
            print(f"{i+1}. {item}{equipped}")
        
        print(f"\n{len(equipment)+1}. Cancel")
        
        try:
            choice = int(input(f"\nSelect equipment to equip (1-{len(equipment)+1}): "))
            
            if 1 <= choice <= len(equipment):
                idx = equipment[choice-1][0]
                item = self.player.inventory[idx]
                
                if isinstance(item, Weapon):
                    self.player.equip_weapon(idx)
                elif isinstance(item, Armor):
                    self.player.equip_armor(idx)
                
                self.wait_for_input()
                
            elif choice == len(equipment)+1:
                return
                
            else:
                print("Invalid choice. Please try again.")
                self.wait_for_input()
                self.equip_item()
                
        except ValueError:
            print("Please enter a valid number.")
            self.wait_for_input()
            self.equip_item()
    
    def use_item(self):
        """使用物品界面"""
        self.clear_screen()
        self.print_header("USE ITEM")
        
        usable_items = [(i, item) for i, item in enumerate(self.player.inventory) 
                        if isinstance(item, Potion)]
        
        if not usable_items:
            self.slow_print("You don't have any usable items!")
            self.wait_for_input()
            return
        
        print("Usable Items:")
        for i, (idx, item) in enumerate(usable_items):
            print(f"{i+1}. {item}")
        
        print(f"\n{len(usable_items)+1}. Cancel")
        
        try:
            choice = int(input(f"\nSelect item to use (1-{len(usable_items)+1}): "))
            
            if 1 <= choice <= len(usable_items):
                idx = usable_items[choice-1][0]
                self.player.use_potion(idx)
                self.wait_for_input()
                
            elif choice == len(usable_items)+1:
                return
                
            else:
                print("Invalid choice. Please try again.")
                self.wait_for_input()
                self.use_item()
                
        except ValueError:
            print("Please enter a valid number.")
            self.wait_for_input()
            self.use_item()
    
    def run(self):
        """运行游戏主循环"""
        while self.state != GameState.QUIT:
            if self.state == GameState.MAIN_MENU:
                self.show_main_menu()
            elif self.state == GameState.PLAYING:
                self.show_game_menu()
            elif self.state == GameState.BATTLE:
                self.battle()
            elif self.state == GameState.SHOP:
                self.show_shop()
            elif self.state == GameState.INVENTORY:
                self.show_inventory()
            elif self.state == GameState.GAME_OVER:
                self.game_over()
        
        self.clear_screen()
        self.slow_print("Thank you for playing Dungeon Adventure!", 0.05)
        self.slow_print("Goodbye!", 0.05)


# 运行游戏
if __name__ == "__main__":
    game = Game()
    game.run()

4.创建一个自定义容器

# 自定义容器类实现

class MultiContainer:
    """
    一个多功能容器类,结合了列表和字典的特性
    可以通过索引或键来访问元素
    """
    def __init__(self, items=None):
        # 内部存储结构
        self._list_data = []  # 按顺序存储元素
        self._dict_data = {}  # 通过键存储元素
        self._key_index_map = {}  # 映射键到索引
        
        # 初始化数据
        if items:
            if isinstance(items, dict):
                for key, value in items.items():
                    self.add(value, key)
            elif isinstance(items, (list, tuple)):
                for item in items:
                    self.add(item)
    
    def add(self, item, key=None):
        """
        添加元素到容器
        如果提供了key,则可以通过key访问
        否则只能通过索引访问
        """
        index = len(self._list_data)
        self._list_data.append(item)
        
        if key is not None:
            if key in self._dict_data:
                # 如果键已存在,更新对应的值和索引
                old_index = self._key_index_map[key]
                self._dict_data[key] = item
                self._key_index_map[key] = index
                # 注意:这会导致旧索引位置的值被覆盖,但在列表中仍然保留
            else:
                # 添加新键值对
                self._dict_data[key] = item
                self._key_index_map[key] = index
        
        return index
    
    def remove(self, key_or_index):
        """
        从容器中移除元素
        可以通过键或索引移除
        """
        if isinstance(key_or_index, int):
            # 通过索引移除
            if 0 <= key_or_index < len(self._list_data):
                # 找到对应的键(如果存在)并从字典中移除
                keys_to_remove = []
                for key, idx in self._key_index_map.items():
                    if idx == key_or_index:
                        keys_to_remove.append(key)
                    elif idx > key_or_index:
                        # 更新大于被删除索引的索引映射
                        self._key_index_map[key] = idx - 1
                
                for key in keys_to_remove:
                    del self._dict_data[key]
                    del self._key_index_map[key]
                
                # 从列表中移除
                self._list_data.pop(key_or_index)
                return True
            return False
        else:
            # 通过键移除
            if key_or_index in self._dict_data:
                index = self._key_index_map[key_or_index]
                del self._dict_data[key_or_index]
                del self._key_index_map[key_or_index]
                
                # 从列表中移除
                self._list_data.pop(index)
                
                # 更新所有大于index的索引映射
                for key, idx in self._key_index_map.items():
                    if idx > index:
                        self._key_index_map[key] = idx - 1
                
                return True
            return False
    
    def __getitem__(self, key_or_index):
        """
        实现 container[key] 或 container[index] 语法
        """
        if isinstance(key_or_index, int):
            # 通过索引访问
            if 0 <= key_or_index < len(self._list_data):
                return self._list_data[key_or_index]
            raise IndexError("Index out of range")
        else:
            # 通过键访问
            if key_or_index in self._dict_data:
                return self._dict_data[key_or_index]
            raise KeyError(f"Key '{key_or_index}' not found")
    
    def __setitem__(self, key_or_index, value):
        """
        实现 container[key] = value 或 container[index] = value 语法
        """
        if isinstance(key_or_index, int):
            # 通过索引设置
            if 0 <= key_or_index < len(self._list_data):
                # 更新列表中的值
                self._list_data[key_or_index] = value
                
                # 更新字典中对应索引的值(如果有)
                for key, idx in self._key_index_map.items():
                    if idx == key_or_index:
                        self._dict_data[key] = value
                return
            raise IndexError("Index out of range")
        else:
            # 通过键设置
            if key_or_index in self._dict_data:
                # 更新现有键的值
                index = self._key_index_map[key_or_index]
                self._dict_data[key_or_index] = value
                self._list_data[index] = value
            else:
                # 添加新键值对
                self.add(value, key_or_index)
    
    def __delitem__(self, key_or_index):
        """
        实现 del container[key] 或 del container[index] 语法
        """
        if not self.remove(key_or_index):
            if isinstance(key_or_index, int):
                raise IndexError("Index out of range")
            else:
                raise KeyError(f"Key '{key_or_index}' not found")
    
    def __contains__(self, item_or_key):
        """
        实现 item in container 或 key in container 语法
        """
        # 先检查是否为键
        if item_or_key in self._dict_data:
            return True
        # 再检查是否为值
        return item_or_key in self._list_data
    
    def __len__(self):
        """
        实现 len(container) 语法
        """
        return len(self._list_data)
    
    def __iter__(self):
        """
        实现迭代器协议,允许 for item in container 语法
        默认按列表顺序迭代
        """
        return iter(self._list_data)
    
    def items(self):
        """
        返回所有键值对,类似字典的 items() 方法
        """
        return self._dict_data.items()
    
    def keys(self):
        """
        返回所有键,类似字典的 keys() 方法
        """
        return self._dict_data.keys()
    
    def values(self):
        """
        返回所有值,类似字典的 values() 方法
        注意:这与直接迭代容器不同,这只返回有键的值
        """
        return self._dict_data.values()
    
    def get(self, key, default=None):
        """
        通过键获取值,如果键不存在则返回默认值
        类似字典的 get() 方法
        """
        return self._dict_data.get(key, default)
    
    def get_by_index(self, index, default=None):
        """
        通过索引获取值,如果索引不存在则返回默认值
        """
        if 0 <= index < len(self._list_data):
            return self._list_data[index]
        return default
    
    def get_index(self, key):
        """
        获取键对应的索引
        """
        if key in self._key_index_map:
            return self._key_index_map[key]
        raise KeyError(f"Key '{key}' not found")
    
    def get_key(self, index):
        """
        获取索引对应的键(如果有)
        """
        for key, idx in self._key_index_map.items():
            if idx == index:
                return key
        return None
    
    def pop(self, key_or_index, default=None):
        """
        移除并返回指定键或索引的元素
        如果不存在,返回默认值
        """
        try:
            value = self[key_or_index]
            self.remove(key_or_index)
            return value
        except (KeyError, IndexError):
            if default is not None:
                return default
            raise
    
    def clear(self):
        """
        清空容器
        """
        self._list_data.clear()
        self._dict_data.clear()
        self._key_index_map.clear()
    
    def update(self, other):
        """
        使用另一个容器或字典更新当前容器
        """
        if isinstance(other, MultiContainer):
            for key, value in other.items():
                self[key] = value
            # 添加没有键的元素
            for i, item in enumerate(other):
                if other.get_key(i) is None:
                    self.add(item)
        elif isinstance(other, dict):
            for key, value in other.items():
                self[key] = value
        elif isinstance(other, (list, tuple)):
            for item in other:
                self.add(item)
    
    def __str__(self):
        """
        字符串表示
        """
        list_repr = str(self._list_data)
        dict_repr = str({k: self._dict_data[k] for k in self._dict_data})
        return f"MultiContainer(list={list_repr}, dict={dict_repr})"
    
    def __repr__(self):
        return self.__str__()


# 测试代码
if __name__ == "__main__":
    # 创建一个空容器
    container = MultiContainer()
    
    # 添加元素
    container.add("apple")  # 只能通过索引访问
    container.add("banana", "yellow_fruit")  # 可以通过键"yellow_fruit"或索引1访问
    container.add("cherry", "red_fruit")
    
    print("Container after adding elements:", container)
    
    # 通过索引访问
    print("\nAccessing by index:")
    print("container[0]:", container[0])
    print("container[1]:", container[1])
    
    # 通过键访问
    print("\nAccessing by key:")
    print("container['yellow_fruit']:", container["yellow_fruit"])
    print("container['red_fruit']:", container["red_fruit"])
    
    # 修改元素
    container[0] = "green_apple"
    container["yellow_fruit"] = "ripe_banana"
    
    print("\nContainer after modifying elements:", container)
    
    # 使用get方法
    print("\nUsing get methods:")
    print("container.get('yellow_fruit'):", container.get("yellow_fruit"))
    print("container.get('missing_key', 'default'):", container.get("missing_key", "default"))
    print("container.get_by_index(0):", container.get_by_index(0))
    
    # 检查成员关系
    print("\nMembership tests:")
    print("'green_apple' in container:", "green_apple" in container)
    print("'yellow_fruit' in container:", "yellow_fruit" in container)
    print("'orange' in container:", "orange" in container)
    
    # 长度
    print("\nLength of container:", len(container))
    
    # 迭代
    print("\nIterating over container:")
    for item in container:
        print(f"  {item}")
    
    # 键和值
    print("\nKeys:", list(container.keys()))
    print("Values (with keys):", list(container.values()))
    print("Items:", list(container.items()))
    
    # 索引和键的关系
    print("\nIndex-key relationships:")
    for i in range(len(container)):
        key = container.get_key(i)
        value = container[i]
        print(f"  Index {i}: Key = {key}, Value = {value}")
    
    # 移除元素
    print("\nRemoving elements:")
    removed_item = container.pop("yellow_fruit")
    print(f"Removed 'yellow_fruit': {removed_item}")
    print("Container after removal:", container)
    
    # 更新容器
    print("\nUpdating container:")
    container.update({"new_key": "new_value", "red_fruit": "strawberry"})
    container.update(["orange", "grape"])
    print("Container after update:", container)
    
    # 清空容器
    container.clear()
    print("\nContainer after clearing:", container)
    
    # 使用字典初始化
    dict_container = MultiContainer({"a": 1, "b": 2, "c": 3})
    print("\nContainer initialized with dict:", dict_container)
    
    # 使用列表初始化
    list_container = MultiContainer([10, 20, 30, 40])
    print("Container initialized with list:", list_container)

你可能感兴趣的:(Python3,python,开发语言)