python编程-第九节-类-002

Python面向对象编程:从餐馆到用户的欢乐编程之旅 🎪

1. 餐馆大亨速成班 🍽️

让我们开启Python餐馆创业之旅!

首先,我们需要一个`Restaurant`类来打造我们的美食帝国:

class Restaurant:
    def __init__(self, name, cuisine):
        self.restaurant_name = name  # 餐馆名字
        self.cuisine_type = cuisine  # 菜系类型
        self.is_open = False  # 偷偷加个营业状态
    
    def describe_restaurant(self):
        print(f"欢迎来到'{self.restaurant_name}'!")
        print(f"我们专营:{self.cuisine_type}美食")
        if self.is_open:
            print("(目前正在营业中,快来吃吧!)")
    
    def open_restaurant(self):
        self.is_open = True
        print(f"{self.restaurant_name}开门迎客啦!")
        print("厨师们正在挥舞锅铲,服务员已就位!")

现在让我们开张第一家店试试:

my_diner = Restaurant("代码小厨", "Python风味")
print(f"店名:{my_diner.restaurant_name}")
print(f"特色:{my_diner.cuisine_type}")

my_diner.describe_restaurant()
my_diner.open_restaurant()

2. 连锁经营梦想 🌟

既然第一家店这么成功,不如开三家分店吧!

# 三家不同风味的餐馆
restaurant1 = Restaurant("字节跳动小吃", "算法烧烤")
restaurant2 = Restaurant("深度求索茶餐厅", "AI点心")
restaurant3 = Restaurant("Python披萨", "面向对象风味")

# 展示我们的餐饮帝国
print("
=== 我们的餐饮集团旗下品牌 ===")
for r in [restaurant1, restaurant2, restaurant3]:
    r.describe_restaurant()
    print("---")

3. 用户管理系统 👥

餐馆有了,现在需要记录我们的VIP顾客:

class User:
    def __init__(self, first, last, age, favorite_food):
        self.first_name = first
        self.last_name = last
        self.age = age
        self.favorite_food = favorite_food
        self.loyalty_points = 0  # 会员积分
    
    def describe_user(self):
        print(f"用户档案:{self.first_name} {self.last_name}")
        print(f"年龄:{self.age} | 最爱食物:{self.favorite_food}")
        print(f"当前积分:{self.loyalty_points}")
    
    def greet_user(self):
        print(f"亲爱的{self.first_name},今天想来点{self.favorite_food}吗?")
    
    def add_points(self, points):
        self.loyalty_points += points
        print(f"积分+{points}!现在共有{self.loyalty_points}分")

让我们创建几位尊贵的顾客:

# 三位VIP用户
user1 = User("张", "三", 28, "Python披萨")
user2 = User("李", "四", 35, "算法烧烤")
user3 = User("王", "五", 22, "AI点心")

# 热情招待
print("
=== 今日VIP客户 ===")
for u in [user1, user2, user3]:
    u.greet_user()
    u.describe_user()
    u.add_points(100)  # 首次到店赠送积分
    print("---")

4. 功能升级建议 🚀

想让你的代码更精彩?试试这些扩展:

1. 给`Restaurant`类添加`served_customers`属性,记录服务人数
2. 为`User`类添加`dietary_restrictions`属性,记录饮食限制
3. 创建一个`PremiumUser`子类,提供专属特权
4. 添加方法让用户可以兑换积分换取免费餐点

记住,编程就像开餐馆——最重要的是让”顾客”(也就是使用你代码的人)感到愉快!

现在就去打造你的代码美食帝国吧!👨‍🍳👩‍🍳

9.2 玩转类和实例:让你的代码活起来  

9.2.1 从”造车”开始理解面向对象  

想象一下,你突然获得了造车超能力!

在编程世界里,类就是你的汽车工厂蓝图,而实例就是一辆辆从生产线上下来的具体汽车。  

# 汽车制造厂开工啦!
class Car:
    """这不是普通的车,这是代码界的变形金刚!"""
    
    def __init__(self, make, model, year):
        """给新车安装'身份证'"""
        self.make = make    # 品牌
        self.model = model  # 型号
        self.year = year    # 出厂年份
        self.odometer = 0   # 新车里程表从0开始
    
    def get_car_info(self):
        """生成炫酷的汽车名片"""
        return f"✨ {self.year}款 {self.make} {self.model} ✨"
    
    def road_trip(self, miles):
        """来场说走就走的旅行"""
        self.odometer += miles
        print(f"又跑了{miles}英里!总里程:{self.odometer}")

# 造一辆梦想座驾
my_dream_car = Car('特斯拉', 'Cybertruck', 2024)
print(my_dream_car.get_car_info())  # 输出:✨ 2024款 特斯拉 Cybertruck ✨

# 开车去兜风
my_dream_car.road_trip(100)
my_dream_car.road_trip(50)

这个造车厂有什么魔法?

1. __init__方法:就像汽车出厂前的最后装配线,给每辆车装上必备零件(属性)
2. 自定义方法:让车不仅能展示信息(get_car_info),还能记录里程(road_trip)
3. 实例化:`my_dream_car`就是根据蓝图打造的具体车辆

为什么这比单独变量更酷?

– 封装性:所有汽车相关数据和功能都打包在一起
– 可扩展性:想加新功能?直接给类添加方法就行
– 复用性:造100辆车和造1辆车的代码量几乎一样

程序员小贴士:当你发现自己在复制粘贴相似的变量和函数时,就是时候考虑用类来整理了!

就像把散落的乐高积木分类装盒,代码会变得清爽又强大。

接下来想给你的车加什么功能?

自动驾驶?

变形功能?

还是车载咖啡机?

类的魅力就在于,只要你能想到,就能实现!

9.2.2 属性默认值:让你的代码自带”出厂设置”

(程序员小剧场)
程序员A:”每次实例化都要手动初始化属性好麻烦啊!”
程序员B:”试试默认值吧,就像给变量设置'出厂设置'!”

在Python的类设计中,我们可以像给新手机预装APP一样,为属性设置默认值。

这招特别适合那些”与生俱来”就应该有初始值的属性。

里程表从零开始的哲学

想象你买了一辆全新汽车,它的里程表不应该从”随机数”开始吧?

让我们给Car类加点料:

class Car:
    def __init__(self, make, model, year):
        """汽车的基本身份证"""
        self.make = make      # 品牌
        self.model = model    # 型号
        self.year = year      # 出厂年份
        self.odometer = 0     # 新车当然从零开始!(默认值魔法在这里)
    
    def check_mileage(self):
        """查看里程数的优雅方式"""
        print(f"当前里程:{self.odometer}公里(别担心,不是英里!)")

代码解读时刻:
1. `odometer = 0` 这个默认值就像汽车的”出厂设置”
2. 现在每辆新车都会自动获得一个归零的里程表
3. `check_mileage()`方法比直接print优雅多了(而且我们很贴心地用了公里制)

现实世界小知识:
– 国内新车里程一般在50公里内都算正常(运输过程总要开一开)
– 特斯拉等电动车会显示”总里程”和”本次充电后里程”(要不要给你的类也加这个功能?)

使用示例:

my_tesla = Car('特斯拉', 'Model Y', 2023)
print(f"喜提新车:{my_tesla.year}款{my_tesla.make}{my_tesla.model}")
my_tesla.check_mileage()  # 输出:当前里程:0公里(不是英里!)

程序员吐槽时间:
“那些把里程表默认值设成10000的程序员,你们是不是二手车商派来的卧底?”

(思考题:如果要给电动车添加”剩余电量”属性,你觉得默认值应该设多少?)

扩展案例(选读)

智能家居控制系统

下面我将设计一个完整的智能家居控制系统案例,展示Python面向对象编程的高级特性,包括继承、多态、抽象类、属性装饰器、类方法、静态方法、运算符重载等。

案例概述

我将构建一个智能家居控制系统,包含以下组件:
– 设备基类及各种智能设备
– 房间管理
– 场景模式
– 能源管理
– 异常处理
– 数据持久化

from abc import ABC, abstractmethod
from datetime import datetime
import json
import random
from typing import Dict, List, Optional, Union

class HomeAutomationException(Exception):
    """自定义智能家居异常基类"""
    pass


class Device(ABC):
    """抽象设备基类"""
    
    _instances = 0  # 类变量,记录创建的设备实例数
    
    def __init__(self, name: str, power_consumption: float):
        self._name = name
        self._power = power_consumption
        self._status = False
        self._id = Device._instances
        Device._instances += 1
        
    @property
    def name(self) -> str:
        return self._name
    
    @name.setter
    def name(self, value: str):
        if not value or not isinstance(value, str):
            raise ValueError("设备名称必须是非空字符串")
        self._name = value
        
    @property
    def power_consumption(self) -> float:
        return self._power
    
    @property
    def status(self) -> bool:
        return self._status
    
    @abstractmethod
    def turn_on(self):
        """抽象方法,开启设备"""
        pass
    
    @abstractmethod
    def turn_off(self):
        """抽象方法,关闭设备"""
        pass
    
    def __str__(self) -> str:
        return f"{self.__class__.__name__}(name={self.name}, status={self.status})"
    
    def __repr__(self) -> str:
        return f"<{self.__class__.__name__} id={self._id} name='{self.name}'>"
    
    def __eq__(self, other) -> bool:
        if not isinstance(other, Device):
            return False
        return self._id == other._id
    
    def __hash__(self) -> int:
        return hash(self._id)
    
    @classmethod
    def get_instance_count(cls) -> int:
        """类方法,获取创建的设备实例数"""
        return cls._instances
    
    @staticmethod
    def validate_power(power: float) -> bool:
        """静态方法,验证功率值是否合理"""
        return 0 <= power <= 10000


class SmartLight(Device):
    """智能灯光类"""
    
    def __init__(self, name: str, brightness: int = 50, color_temp: str = "warm"):
        super().__init__(name, power_consumption=10.5)
        self._brightness = brightness
        self._color_temp = color_temp
        self._transition_speed = 1.0
        
    @property
    def brightness(self) -> int:
        return self._brightness
    
    @brightness.setter
    def brightness(self, value: int):
        if not 0 <= value <= 100:
            raise ValueError("亮度值必须在0-100之间")
        self._brightness = value
        
    def turn_on(self):
        if self._status:
            print(f"{self.name} 已经处于开启状态")
            return
        self._status = True
        print(f"{self.name} 灯光已开启,亮度 {self.brightness}%")
        
    def turn_off(self):
        if not self._status:
            print(f"{self.name} 已经处于关闭状态")
            return
        self._status = False
        print(f"{self.name} 灯光已关闭")
        
    def dim(self, target_brightness: int, duration: float = 1.0):
        """渐变调整亮度"""
        if not self._status:
            raise HomeAutomationException("无法调整亮度:灯光未开启")
            
        print(f"{self.name} 亮度从 {self.brightness}% 渐变到 {target_brightness}%")
        self.brightness = target_brightness
        self._transition_speed = duration
        
    def __add__(self, other: int) -> 'SmartLight':
        """重载+运算符,增加亮度"""
        if not isinstance(other, int):
            raise TypeError("只能与整数相加")
            
        new_brightness = min(100, self.brightness + other)
        self.dim(new_brightness)
        return self


class SmartThermostat(Device):
    """智能温控器类"""
    
    def __init__(self, name: str, current_temp: float = 22.0, target_temp: float = 22.0):
        super().__init__(name, power_consumption=15.0)
        self._current_temp = current_temp
        self._target_temp = target_temp
        self._mode = "cool"  # heat/cool/auto/off
        
    def turn_on(self):
        if self._status:
            print(f"{self.name} 已经处于开启状态")
            return
        self._status = True
        print(f"{self.name} 温控器已开启,当前温度 {self._current_temp}°C")
        
    def turn_off(self):
        if not self._status:
            print(f"{self.name} 已经处于关闭状态")
            return
        self._status = False
        print(f"{self.name} 温控器已关闭")
        
    def set_temperature(self, target: float):
        """设置目标温度"""
        if not self._status:
            raise HomeAutomationException("无法设置温度:温控器未开启")
            
        self._target_temp = target
        print(f"{self.name} 目标温度设置为 {target}°C")
        
    def update_current_temp(self, new_temp: float):
        """更新当前温度(模拟传感器读数)"""
        self._current_temp = new_temp
        if abs(new_temp - self._target_temp) > 2.0 and self._status:
            print(f"{self.name} 温度差异较大,正在调整...")


class SmartLock(Device):
    """智能门锁类"""
    
    def __init__(self, name: str, locked: bool = True):
        super().__init__(name, power_consumption=2.5)
        self._locked = locked
        self._access_codes = {"default": "0000"}
        
    def turn_on(self):
        self.lock()
        
    def turn_off(self):
        self.unlock()
        
    def lock(self):
        self._locked = True
        print(f"{self.name} 已上锁")
        
    def unlock(self, code: Optional[str] = None):
        if code and code not in self._access_codes.values():
            raise HomeAutomationException("无效的解锁码")
        self._locked = False
        print(f"{self.name} 已解锁")
        
    def add_access_code(self, name: str, code: str):
        """添加新的访问码"""
        if not code.isdigit() or len(code) != 4:
            raise ValueError("访问码必须是4位数字")
        self._access_codes[name] = code
        print(f"已为 {name} 添加访问码")


class Room:
    """房间类,包含多个设备"""
    
    def __init__(self, name: str):
        self.name = name
        self._devices: Dict[str, Device] = {}
        
    def add_device(self, device: Device):
        if device.name in self._devices:
            raise HomeAutomationException(f"设备 {device.name} 已存在于房间 {self.name} 中")
        self._devices[device.name] = device
        print(f"已将设备 {device.name} 添加到房间 {self.name}")
        
    def remove_device(self, device_name: str):
        if device_name not in self._devices:
            raise HomeAutomationException(f"设备 {device_name} 不存在于房间 {self.name} 中")
        del self._devices[device_name]
        
    def get_device(self, device_name: str) -> Device:
        return self._devices.get(device_name)
    
    def turn_on_all(self):
        for device in self._devices.values():
            device.turn_on()
            
    def turn_off_all(self):
        for device in self._devices.values():
            device.turn_off()
            
    def get_total_power_consumption(self) -> float:
        return sum(device.power_consumption for device in self._devices.values() 
                  if device.status)
    
    def __contains__(self, device_name: str) -> bool:
        """重载in运算符"""
        return device_name in self._devices
    
    def __iter__(self):
        """使房间对象可迭代"""
        return iter(self._devices.values())
    
    def __len__(self) -> int:
        """重载len()函数"""
        return len(self._devices)


class Scene:
    """场景模式类"""
    
    def __init__(self, name: str):
        self.name = name
        self._actions: List[dict] = []
        
    def add_action(self, device: Device, action: str, **kwargs):
        """添加场景动作"""
        if not hasattr(device, action):
            raise HomeAutomationException(f"设备 {device.name} 不支持动作 {action}")
            
        self._actions.append({
            'device': device,
            'action': action,
            'kwargs': kwargs
        })
        
    def execute(self):
        """执行场景"""
        print(f"正在执行场景: {self.name}")
        for action in self._actions:
            device = action['device']
            method = getattr(device, action['action'])
            method(**action['kwargs'])


class SmartHome:
    """智能家居主控制系统"""
    
    def __init__(self, name: str):
        self.name = name
        self._rooms: Dict[str, Room] = {}
        self._scenes: Dict[str, Scene] = {}
        self._energy_usage: Dict[datetime, float] = {}
        
    def add_room(self, room: Room):
        if room.name in self._rooms:
            raise HomeAutomationException(f"房间 {room.name} 已存在")
        self._rooms[room.name] = room
        print(f"已添加房间: {room.name}")
        
    def get_room(self, room_name: str) -> Room:
        return self._rooms.get(room_name)
    
    def add_scene(self, scene: Scene):
        if scene.name in self._scenes:
            raise HomeAutomationException(f"场景 {scene.name} 已存在")
        self._scenes[scene.name] = scene
        
    def execute_scene(self, scene_name: str):
        if scene_name not in self._scenes:
            raise HomeAutomationException(f"场景 {scene_name} 不存在")
        self._scenes[scene_name].execute()
        
    def record_energy_usage(self):
        """记录当前能源使用情况"""
        total_power = sum(
            room.get_total_power_consumption()
            for room in self._rooms.values()
        )
        self._energy_usage[datetime.now()] = total_power
        return total_power
    
    def get_daily_energy_report(self) -> Dict[str, float]:
        """生成每日能源报告"""
        report = {}
        for timestamp, power in self._energy_usage.items():
            date_str = timestamp.strftime("%Y-%m-%d")
            report[date_str] = report.get(date_str, 0) + power
        return report
    
    def save_to_json(self, filename: str):
        """将家居配置保存到JSON文件"""
        data = {
            'name': self.name,
            'rooms': {
                room_name: {
                    'devices': [
                        {
                            'type': device.__class__.__name__,
                            'name': device.name,
                            'power': device.power_consumption,
                            'status': device.status
                        }
                        for device in room
                    ]
                }
                for room_name, room in self._rooms.items()
            },
            'scenes': {
                scene_name: [
                    {
                        'device': action['device'].name,
                        'action': action['action'],
                        'kwargs': action['kwargs']
                    }
                    for action in scene._actions
                ]
                for scene_name, scene in self._scenes.items()
            }
        }
        
        with open(filename, 'w') as f:
            json.dump(data, f, indent=4)
            
    @classmethod
    def load_from_json(cls, filename: str) -> 'SmartHome':
        """从JSON文件加载家居配置"""
        with open(filename) as f:
            data = json.load(f)
            
        home = cls(data['name'])
        
        # 设备工厂函数
        def create_device(device_data: dict) -> Device:
            device_type = device_data['type']
            name = device_data['name']
            
            if device_type == 'SmartLight':
                return SmartLight(name)
            elif device_type == 'SmartThermostat':
                return SmartThermostat(name)
            elif device_type == 'SmartLock':
                return SmartLock(name)
            else:
                raise ValueError(f"未知设备类型: {device_type}")
        
        # 重建房间和设备
        for room_name, room_data in data['rooms'].items():
            room = Room(room_name)
            for device_data in room_data['devices']:
                device = create_device(device_data)
                if device_data['status']:
                    device.turn_on()
                room.add_device(device)
            home.add_room(room)
        
        # 重建场景
        for scene_name, actions in data['scenes'].items():
            scene = Scene(scene_name)
            for action in actions:
                # 查找设备
                device = None
                for room in home._rooms.values():
                    if action['device'] in room:
                        device = room.get_device(action['device'])
                        break
                
                if device:
                    scene.add_action(device, action['action'], **action['kwargs'])
            home.add_scene(scene)
            
        return home


# 示例使用
def demo_smart_home():
    print("
=== 智能家居系统演示 ===")
    
    # 创建家居实例
    my_home = SmartHome("我的智能家居")
    
    # 创建房间
    living_room = Room("客厅")
    bedroom = Room("卧室")
    
    # 创建设备
    light1 = SmartLight("客厅主灯")
    light2 = SmartLight("客厅氛围灯", brightness=30)
    thermostat = SmartThermostat("客厅温控器", current_temp=24.5)
    lock = SmartLock("前门锁")
    bed_light = SmartLight("床头灯")
    
    # 添加设备到房间
    living_room.add_device(light1)
    living_room.add_device(light2)
    living_room.add_device(thermostat)
    living_room.add_device(lock)
    bedroom.add_device(bed_light)
    
    # 添加房间到家居
    my_home.add_room(living_room)
    my_home.add_room(bedroom)
    
    # 创建场景
    evening_scene = Scene("晚间模式")
    evening_scene.add_action(light1, "turn_on")
    evening_scene.add_action(light2, "turn_on")
    evening_scene.add_action(light2, "dim", target_brightness=50)
    evening_scene.add_action(thermostat, "set_temperature", target=22.0)
    evening_scene.add_action(lock, "lock")
    
    my_home.add_scene(evening_scene)
    
    # 执行场景
    my_home.execute_scene("晚间模式")
    
    # 使用运算符重载
    light1 + 20  # 增加亮度20%
    
    # 能源记录
    my_home.record_energy_usage()
    
    # 保存配置
    my_home.save_to_json("my_smart_home.json")
    
    # 从文件加载
    loaded_home = SmartHome.load_from_json("my_smart_home.json")
    print(f"
从文件加载的家居: {loaded_home.name}")
    
    # 演示迭代器
    print("
客厅设备:")
    for device in living_room:
        print(f"- {device}")
    
    # 演示异常处理
    try:
        light1.dim(120)  # 无效亮度值
    except HomeAutomationException as e:
        print(f"
捕获到异常: {e}")


if __name__ == "__main__":
    demo_smart_home()

案例解析

1. 抽象基类与继承
– `Device` 是抽象基类,定义了所有智能设备的通用接口
– 具体设备类 (`SmartLight`, `SmartThermostat`, `SmartLock`) 继承并实现抽象方法

2. 高级面向对象特性
– 属性装饰器: 使用 `@property` 和 `@setter` 控制属性访问
– 类方法与静态方法 `get_instance_count()` 和 `validate_power()`
– 运算符重载: `__add__`, `__contains__`, `__iter__` 等
– 抽象方法: 强制子类实现特定方法

3. 组合与聚合
– `Room` 包含多个 `Device` 对象
– `SmartHome` 包含多个 `Room` 和 `Scene` 对象

4. 异常处理
– 自定义 `HomeAutomationException` 异常类
– 各种验证和错误处理逻辑

5. 数据持久化
– `save_to_json()` 和 `load_from_json()` 方法实现配置的保存与加载

6. 类型提示
– 全面使用 Python 类型提示 (`: str`, `-> bool` 等)

7. 设计模式应用
– 工厂模式: 在 `load_from_json()` 中根据类型创建设备
– 组合模式: `Scene` 类组合多个设备动作

这个案例展示了 Python 面向对象编程的深度应用,涵盖了实际开发中常见的需求和设计考量。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容