Python教程42:综合项目-图书管理系统

Python教程42:综合项目-图书管理系统 “纸上得来终觉浅,绝知此事要躬行。” 经过第四部分12课的学习,我们掌握了OOP的核心概念。今天通过一个完整的图书管理系统,综合运用所学知识。 1. 项目需求 功能需求 基本功能: 图书管理:添加、删除、搜索、借阅、归还 用户管理:注册、借阅记录 分类管理:按类别组织图书 进阶功能: 数据持久化(JSON) 借阅期限和逾期管理 统计报表 技术要求 使用类和对象 继承和多态 抽象基类 属性管理(@property) 异常处理 文件操作 2. 系统设计 类设计 Library System ├── Book(图书基类) │ ├── PhysicalBook(实体书) │ └── EBook(电子书) ├── User(用户类) ├── Library(图书馆类) ├── BorrowRecord(借阅记录) └── Storage(存储类) 3. 核心实现 Book基类 1from abc import ABC, abstractmethod 2from datetime import datetime 3 4class Book(ABC): 5 """图书抽象基类""" 6 7 def __init__(self, isbn, title, author, category): 8 self.isbn = isbn 9 self.title = title 10 self.author = author 11 self.category = category 12 self.is_borrowed = False 13 14 @abstractmethod 15 def get_type(self): 16 """获取图书类型""" 17 pass 18 19 def to_dict(self): 20 """序列化""" 21 return { 22 'isbn': self.isbn, 23 'title': self.title, 24 'author': self.author, 25 'category': self.category, 26 'is_borrowed': self.is_borrowed, 27 'type': self.get_type() 28 } 29 30 def __str__(self): 31 status = "已借出" if self.is_borrowed else "可借阅" 32 return f"{self.title} by {self.author} ({status})" 33 34class PhysicalBook(Book): 35 """实体书""" 36 def __init__(self, isbn, title, author, category, location): 37 super().__init__(isbn, title, author, category) 38 self.location = location # 书架位置 39 40 def get_type(self): 41 return "physical" 42 43 def to_dict(self): 44 data = super().to_dict() 45 data['location'] = self.location 46 return data 47 48class EBook(Book): 49 """电子书""" 50 def __init__(self, isbn, title, author, category, file_size): 51 super().__init__(isbn, title, author, category) 52 self.file_size = file_size # 文件大小(MB) 53 54 def get_type(self): 55 return "ebook" 56 57 def to_dict(self): 58 data = super().to_dict() 59 data['file_size'] = self.file_size 60 return data User类 1class User: 2 """用户类""" 3 4 def __init__(self, user_id, name, email): 5 self.user_id = user_id 6 self.name = name 7 self.email = email 8 self.borrowed_books = [] # ISBN列表 9 10 def can_borrow(self, max_books=5): 11 """检查是否可以借阅""" 12 return len(self.borrowed_books) < max_books 13 14 def borrow_book(self, isbn): 15 """借阅图书""" 16 if isbn not in self.borrowed_books: 17 self.borrowed_books.append(isbn) 18 19 def return_book(self, isbn): 20 """归还图书""" 21 if isbn in self.borrowed_books: 22 self.borrowed_books.remove(isbn) 23 24 def to_dict(self): 25 return { 26 'user_id': self.user_id, 27 'name': self.name, 28 'email': self.email, 29 'borrowed_books': self.borrowed_books 30 } 31 32 def __str__(self): 33 return f"User({self.name}, 已借{len(self.borrowed_books)}本)" BorrowRecord类 1class BorrowRecord: 2 """借阅记录""" 3 4 def __init__(self, user_id, isbn, borrow_date=None): 5 self.user_id = user_id 6 self.isbn = isbn 7 self.borrow_date = borrow_date or datetime.now() 8 self.return_date = None 9 self.due_date = self.borrow_date + timedelta(days=30) 10 11 @property 12 def is_overdue(self): 13 """是否逾期""" 14 if self.return_date: 15 return False 16 return datetime.now() > self.due_date 17 18 def mark_returned(self): 19 """标记为已归还""" 20 self.return_date = datetime.now() 21 22 def to_dict(self): 23 return { 24 'user_id': self.user_id, 25 'isbn': self.isbn, 26 'borrow_date': self.borrow_date.isoformat(), 27 'due_date': self.due_date.isoformat(), 28 'return_date': self.return_date.isoformat() if self.return_date else None 29 } Library类 1class Library: 2 """图书馆类""" 3 4 def __init__(self, name): 5 self.name = name 6 self.books = {} # ISBN -> Book 7 self.users = {} # user_id -> User 8 self.records = [] # BorrowRecord列表 9 10 def add_book(self, book): 11 """添加图书""" 12 if book.isbn in self.books: 13 raise ValueError(f"图书{book.isbn}已存在") 14 self.books[book.isbn] = book 15 16 def remove_book(self, isbn): 17 """删除图书""" 18 if isbn not in self.books: 19 raise ValueError(f"图书{isbn}不存在") 20 if self.books[isbn].is_borrowed: 21 raise ValueError("图书已借出,无法删除") 22 del self.books[isbn] 23 24 def register_user(self, user): 25 """注册用户""" 26 if user.user_id in self.users: 27 raise ValueError(f"用户{user.user_id}已存在") 28 self.users[user.user_id] = user 29 30 def borrow_book(self, user_id, isbn): 31 """借阅图书""" 32 # 验证 33 if user_id not in self.users: 34 raise ValueError("用户不存在") 35 if isbn not in self.books: 36 raise ValueError("图书不存在") 37 38 user = self.users[user_id] 39 book = self.books[isbn] 40 41 if book.is_borrowed: 42 raise ValueError("图书已被借出") 43 if not user.can_borrow(): 44 raise ValueError("借阅数量已达上限") 45 46 # 借阅 47 book.is_borrowed = True 48 user.borrow_book(isbn) 49 record = BorrowRecord(user_id, isbn) 50 self.records.append(record) 51 52 return f"{user.name}成功借阅《{book.title}》" 53 54 def return_book(self, user_id, isbn): 55 """归还图书""" 56 if user_id not in self.users: 57 raise ValueError("用户不存在") 58 if isbn not in self.books: 59 raise ValueError("图书不存在") 60 61 user = self.users[user_id] 62 book = self.books[isbn] 63 64 if not book.is_borrowed: 65 raise ValueError("图书未被借出") 66 67 # 归还 68 book.is_borrowed = False 69 user.return_book(isbn) 70 71 # 更新记录 72 for record in reversed(self.records): 73 if (record.user_id == user_id and 74 record.isbn == isbn and 75 not record.return_date): 76 record.mark_returned() 77 break 78 79 return f"{user.name}成功归还《{book.title}》" 80 81 def search_books(self, keyword): 82 """搜索图书""" 83 results = [] 84 keyword = keyword.lower() 85 for book in self.books.values(): 86 if (keyword in book.title.lower() or 87 keyword in book.author.lower() or 88 keyword in book.category.lower()): 89 results.append(book) 90 return results 91 92 def get_statistics(self): 93 """获取统计信息""" 94 total_books = len(self.books) 95 borrowed = sum(1 for book in self.books.values() if book.is_borrowed) 96 overdue = sum(1 for record in self.records if record.is_overdue) 97 98 return { 99 'total_books': total_books, 100 'available': total_books - borrowed, 101 'borrowed': borrowed, 102 'total_users': len(self.users), 103 'overdue_records': overdue 104 } 4. 使用示例 1# 创建图书馆 2library = Library("市图书馆") 3 4# 添加图书 5book1 = PhysicalBook("978-1", "Python编程", "作者A", "编程", "A-101") 6book2 = EBook("978-2", "数据结构", "作者B", "编程", 15.5) 7library.add_book(book1) 8library.add_book(book2) 9 10# 注册用户 11user = User("U001", "张三", "zhang@example.com") 12library.register_user(user) 13 14# 借阅流程 15print(library.borrow_book("U001", "978-1")) 16print(library.borrow_book("U001", "978-2")) 17 18# 搜索 19results = library.search_books("Python") 20for book in results: 21 print(book) 22 23# 统计 24stats = library.get_statistics() 25print(f"总藏书:{stats['total_books']}") 26print(f"可借阅:{stats['available']}") 27print(f"已借出:{stats['borrowed']}") 28 29# 归还 30print(library.return_book("U001", "978-1")) 5. 知识点回顾 这个项目运用了: ...

2026-01-08 · 5 min · 874 words · 老墨

Python教程41:面向对象最佳实践

Python教程41:面向对象最佳实践 “代码是写给人看的,顺便让机器执行。” 经过前面的学习,我们掌握了OOP的所有特性。今天总结Python面向对象的最佳实践,帮助你写出更优质的代码。 1. SOLID原则 S - 单一职责原则(Single Responsibility) 一个类只做一件事: 1# 不好:类职责太多 2class User: 3 def __init__(self, name): 4 self.name = name 5 6 def save_to_database(self): 7 """保存用户""" 8 pass 9 10 def send_email(self): 11 """发送邮件""" 12 pass 13 14# 好:职责分离 15class User: 16 def __init__(self, name): 17 self.name = name 18 19class UserRepository: 20 def save(self, user): 21 """保存用户""" 22 pass 23 24class EmailService: 25 def send(self, user): 26 """发送邮件""" 27 pass O - 开闭原则(Open/Closed) 对扩展开放,对修改关闭: 1# 好:使用多态扩展功能 2class Shape: 3 def area(self): 4 pass 5 6class Circle(Shape): 7 def __init__(self, radius): 8 self.radius = radius 9 10 def area(self): 11 return 3.14 * self.radius ** 2 12 13# 添加新形状无需修改现有代码 14class Rectangle(Shape): 15 def __init__(self, width, height): 16 self.width = width 17 self.height = height 18 19 def area(self): 20 return self.width * self.height L - 里氏替换原则(Liskov Substitution) 子类必须能替换父类: ...

2025-12-26 · 4 min · 727 words · 老墨

Python教程40:常用设计模式

Python教程40:常用设计模式 “不要重复造轮子。” 设计模式是解决常见问题的可复用方案。今天我们学习Python中常用的设计模式,提升代码设计能力。 1. 创建型模式 单例模式(Singleton) 确保类只有一个实例: 1class Singleton: 2 _instance = None 3 4 def __new__(cls): 5 if cls._instance is None: 6 cls._instance = super().__new__(cls) 7 return cls._instance 8 9# 或使用装饰器 10def singleton(cls): 11 instances = {} 12 def get_instance(*args, **kwargs): 13 if cls not in instances: 14 instances[cls] = cls(*args, **kwargs) 15 return instances[cls] 16 return get_instance 17 18@singleton 19class Database: 20 def __init__(self, url): 21 self.url = url 工厂模式(Factory) 根据条件创建不同对象: 1class ShapeFactory: 2 @staticmethod 3 def create_shape(shape_type): 4 if shape_type == "circle": 5 return Circle() 6 elif shape_type == "rectangle": 7 return Rectangle() 8 else: 9 raise ValueError(f"未知形状:{shape_type}") 10 11# 使用 12shape = ShapeFactory.create_shape("circle") 建造者模式(Builder) 分步骤构建复杂对象: 1class QueryBuilder: 2 def __init__(self): 3 self._select = [] 4 self._from = None 5 self._where = [] 6 7 def select(self, *fields): 8 self._select.extend(fields) 9 return self 10 11 def from_table(self, table): 12 self._from = table 13 return self 14 15 def where(self, condition): 16 self._where.append(condition) 17 return self 18 19 def build(self): 20 query = f"SELECT {', '.join(self._select)}" 21 query += f" FROM {self._from}" 22 if self._where: 23 query += f" WHERE {' AND '.join(self._where)}" 24 return query 25 26# 使用(链式调用) 27sql = (QueryBuilder() 28 .select("name", "age") 29 .from_table("users") 30 .where("age > 18") 31 .build()) 2. 结构型模式 适配器模式(Adapter) 使不兼容的接口协同工作: ...

2025-12-11 · 4 min · 658 words · 老墨

Python教程39:元类(Metaclass)

Python教程39:元类(Metaclass) “元类就是深度魔法,99%的用户应该根本不必为此操心。” —— Tim Peters 元类是Python的高级特性,用于创建类的"类"。今天我们揭开元类的神秘面纱,理解Python对象系统的底层机制。 1. 什么是元类 一切皆对象 在Python中,类也是对象: 1class MyClass: 2 pass 3 4# 类是对象 5print(type(MyClass)) # <class 'type'> 6print(isinstance(MyClass, type)) # True 7 8# 类可以赋值、作为参数 9AnotherName = MyClass 10def func(cls): 11 return cls() 元类(Metaclass): 创建类的"类" type是Python的默认元类 类是元类的实例 1# 类是type的实例 2class MyClass: 3 pass 4 5print(type(MyClass)) # <class 'type'> 6 7# 等价于 8MyClass = type('MyClass', (), {}) type的三种用法 1# 用法1:查看对象类型 2print(type(5)) # <class 'int'> 3 4# 用法2:动态创建类 5# type(name, bases, dict) 6MyClass = type('MyClass', (), {'x': 5}) 7obj = MyClass() 8print(obj.x) # 5 9 10# 用法3:作为元类(继承type) 11class MyMeta(type): 12 pass 2. 动态创建类 使用type动态创建类: ...

2025-11-13 · 4 min · 670 words · 老墨

Python教程38:多重继承与MRO

Python教程38:多重继承与MRO “大道至简,大巧若拙。” Python支持多重继承,一个类可以继承多个父类。今天我们学习多重继承的机制、方法解析顺序(MRO)以及如何避免常见陷阱。 1. 什么是多重继承 单继承 vs 多重继承 1# 单继承:一个父类 2class Parent: 3 pass 4 5class Child(Parent): 6 pass 7 8# 多重继承:多个父类 9class Father: 10 def skill(self): 11 return "父亲的技能" 12 13class Mother: 14 def talent(self): 15 return "母亲的天赋" 16 17class Child(Father, Mother): 18 """继承两个父类""" 19 pass 20 21# 子类拥有所有父类的方法 22c = Child() 23print(c.skill()) # 父亲的技能 24print(c.talent()) # 母亲的天赋 2. 方法解析顺序(MRO) 当多个父类有同名方法时,Python如何决定调用哪个? 基本规则 1class A: 2 def method(self): 3 return "A的方法" 4 5class B: 6 def method(self): 7 return "B的方法" 8 9class C(A, B): 10 """继承顺序:A, B""" 11 pass 12 13c = C() 14print(c.method()) # A的方法(优先使用第一个父类) 15 16# 查看MRO 17print(C.__mro__) 18# (<class 'C'>, <class 'A'>, <class 'B'>, <class 'object'>) MRO(Method Resolution Order): ...

2025-10-24 · 4 min · 646 words · 老墨

Python教程37:抽象基类(ABC)

Python教程37:抽象基类(ABC) “约定优于配置。” 抽象基类(Abstract Base Class, ABC)是Python中定义接口规范的机制。今天我们学习如何使用abc模块创建抽象类,强制子类实现特定方法。 1. 什么是抽象基类 问题场景 没有抽象类时,接口规范靠文档和约定: 1class Shape: 2 """ 3 形状基类 4 - 子类应该实现area()和perimeter() 5 - 但没有强制机制 6 """ 7 def area(self): 8 raise NotImplementedError("子类必须实现area方法") 9 10 def perimeter(self): 11 raise NotImplementedError("子类必须实现perimeter方法") 12 13class Circle(Shape): 14 def __init__(self, radius): 15 self.radius = radius 16 17 def area(self): 18 import math 19 return math.pi * self.radius ** 2 20 21 # 忘记实现perimeter()了! 22 23# 问题:可以实例化不完整的类 24c = Circle(5) 25print(c.area()) # OK 26# print(c.perimeter()) # 运行时才报错! 抽象基类解决方案 1from abc import ABC, abstractmethod 2 3class Shape(ABC): 4 """ 5 抽象形状类 6 - 继承ABC 7 - 使用@abstractmethod标记抽象方法 8 - 不能直接实例化 9 - 强制子类实现所有抽象方法 10 """ 11 12 @abstractmethod 13 def area(self): 14 """计算面积(抽象方法)""" 15 pass 16 17 @abstractmethod 18 def perimeter(self): 19 """计算周长(抽象方法)""" 20 pass 21 22class Circle(Shape): 23 def __init__(self, radius): 24 self.radius = radius 25 26 def area(self): 27 import math 28 return math.pi * self.radius ** 2 29 30 # 如果不实现perimeter(),无法实例化 31 32# circle = Shape() # TypeError: 无法实例化抽象类 33 34class CompleteCircle(Shape): 35 def __init__(self, radius): 36 self.radius = radius 37 38 def area(self): 39 import math 40 return math.pi * self.radius ** 2 41 42 def perimeter(self): 43 import math 44 return 2 * math.pi * self.radius 45 46# 完整实现所有抽象方法才能实例化 47c = CompleteCircle(5) 48print(c.area()) # 78.54 49print(c.perimeter()) # 31.42 ABC的优势: ...

2025-10-22 · 5 min · 1005 words · 老墨

Python教程36:属性(Property)与描述符

Python教程36:属性(Property)与描述符 “细节决定成败。” Python提供了强大的属性管理机制,让我们能够优雅地控制属性的访问。今天我们学习@property装饰器和描述符协议,掌握Python属性的高级用法。 1. 为什么需要Property 问题场景 直接访问属性缺乏控制: 1class Person: 2 def __init__(self, age): 3 self.age = age # 公开属性 4 5p = Person(25) 6print(p.age) # 25 7 8# 问题:可以设置非法值 9p.age = -10 # 负数年龄? 10p.age = "abc" # 字符串年龄? 传统解决方法:getter/setter 1class Person: 2 def __init__(self, age): 3 self._age = age # 私有属性 4 5 def get_age(self): 6 """获取年龄""" 7 return self._age 8 9 def set_age(self, value): 10 """设置年龄(带验证)""" 11 if not isinstance(value, int): 12 raise TypeError("年龄必须是整数") 13 if value < 0 or value > 150: 14 raise ValueError("年龄不合理") 15 self._age = value 16 17p = Person(25) 18print(p.get_age()) # 25 19p.set_age(30) # OK 20# p.set_age(-10) # ValueError 问题: 使用不方便:p.get_age()而不是p.age 破坏现有代码:如果后来添加验证,需要修改所有调用 Python解决方案:@property 1class Person: 2 def __init__(self, age): 3 self._age = age 4 5 @property 6 def age(self): 7 """ 8 getter方法 9 - 像访问属性一样调用:p.age 10 - 但实际调用的是方法 11 """ 12 return self._age 13 14 @age.setter 15 def age(self, value): 16 """ 17 setter方法 18 - 像赋值一样调用:p.age = 30 19 - 可以添加验证逻辑 20 """ 21 if not isinstance(value, int): 22 raise TypeError("年龄必须是整数") 23 if value < 0 or value > 150: 24 raise ValueError("年龄不合理") 25 self._age = value 26 27# 使用 28p = Person(25) 29print(p.age) # 调用getter:25 30p.age = 30 # 调用setter:OK 31# p.age = -10 # ValueError 优势: ...

2025-09-14 · 8 min · 1524 words · 老墨

Python教程35:类方法与静态方法

Python教程35:类方法与静态方法 “工欲善其事,必先利其器。” Python提供了三种方法类型:实例方法、类方法、静态方法。今天我们学习类方法(@classmethod)和静态方法(@staticmethod),理解它们的区别和使用场景。 1. 三种方法类型对比 实例方法(Instance Method) 我们最常用的方法: 1class MyClass: 2 def instance_method(self): 3 """ 4 实例方法 5 - 第一个参数是self(实例本身) 6 - 可以访问实例属性和类属性 7 - 通过实例调用 8 """ 9 print(f"Called instance_method of {self}") 10 return "instance method" 11 12obj = MyClass() 13obj.instance_method() # 正常调用 类方法(Class Method) 使用@classmethod装饰器: 1class MyClass: 2 @classmethod 3 def class_method(cls): 4 """ 5 类方法 6 - 第一个参数是cls(类本身) 7 - 可以访问类属性,不能访问实例属性 8 - 通过类或实例调用 9 """ 10 print(f"Called class_method of {cls}") 11 return "class method" 12 13# 通过类调用 14MyClass.class_method() 15 16# 通过实例调用也可以 17obj = MyClass() 18obj.class_method() 静态方法(Static Method) 使用@staticmethod装饰器: ...

2025-08-26 · 6 min · 1150 words · 老墨

Python教程34:魔术方法(Magic Methods)

Python教程34:魔术方法(Magic Methods) “命名即魔法。” Python的魔术方法(也叫特殊方法、双下划线方法)是Python面向对象的核心特性。它们让你的类能够像内置类型一样工作,实现运算符重载、容器协议等高级功能。 1. 什么是魔术方法 魔术方法(Magic Methods): 双下划线开头和结尾的方法:__method__ Python自动调用,不需要显式调用 让类支持Python的特殊语法 也叫"dunder methods"(double underscore) 为什么需要魔术方法: 运算符重载:让对象支持+、-、*等运算 容器协议:让对象可迭代、可索引 上下文管理:支持with语句 对象表示:自定义打印输出 属性访问:控制属性读写 简单示例 1class Point: 2 """二维点""" 3 def __init__(self, x, y): 4 """初始化(魔术方法)""" 5 self.x = x 6 self.y = y 7 8 def __str__(self): 9 """字符串表示(魔术方法)""" 10 return f"Point({self.x}, {self.y})" 11 12 def __add__(self, other): 13 """加法运算符(魔术方法)""" 14 return Point(self.x + other.x, self.y + other.y) 15 16# 使用 17p1 = Point(1, 2) 18p2 = Point(3, 4) 19 20print(p1) # 调用__str__: Point(1, 2) 21p3 = p1 + p2 # 调用__add__ 22print(p3) # Point(4, 6) 2. 对象创建和销毁 new:创建实例 1class Singleton: 2 """ 3 单例模式 4 - __new__在__init__之前调用 5 - __new__负责创建实例 6 - __new__是类方法 7 """ 8 _instance = None 9 10 def __new__(cls): 11 """ 12 创建实例 13 - cls是类本身 14 - 必须返回实例 15 """ 16 if cls._instance is None: 17 print("Creating singleton instance") 18 cls._instance = super().__new__(cls) 19 return cls._instance 20 21 def __init__(self): 22 """初始化实例""" 23 print("Initializing instance") 24 25# 使用 26s1 = Singleton() # Creating singleton instance, Initializing instance 27s2 = Singleton() # Initializing instance (不创建新实例) 28print(s1 is s2) # True(同一个实例) init:初始化 我们已经很熟悉了: ...

2025-07-28 · 8 min · 1524 words · 老墨

Python教程33:多态

Python教程33:多态 “一个接口,多种实现。” 多态是面向对象编程三大特性(封装、继承、多态)的最后一个。今天我们学习Python的多态特性,理解如何让代码更灵活、更易扩展。 1. 什么是多态 多态(Polymorphism): Poly(多个)+ morph(形态) 同一个接口,不同的实现 不同对象对同一消息的不同响应 为什么需要多态: 灵活性:通过父类引用调用子类方法 可扩展:添加新类无需修改现有代码 统一接口:不同对象用相同方式操作 解耦合:调用者不关心对象类型 简单示例 1class Animal: 2 """动物基类""" 3 def speak(self): 4 pass 5 6class Dog(Animal): 7 def speak(self): 8 return "Woof!" 9 10class Cat(Animal): 11 def speak(self): 12 return "Meow!" 13 14class Cow(Animal): 15 def speak(self): 16 return "Moo!" 17 18# 多态:相同的方法调用,不同的行为 19def animal_sound(animal): 20 """ 21 统一的接口 22 - 参数是Animal类型 23 - 不关心具体是什么动物 24 - 调用speak()得到不同的结果 25 """ 26 print(animal.speak()) 27 28# 使用 29animals = [Dog(), Cat(), Cow()] 30for animal in animals: 31 animal_sound(animal) 32# 输出: 33# Woof! 34# Meow! 35# Moo! 多态的好处: ...

2025-06-24 · 5 min · 987 words · 老墨

Python教程32:继承

Python教程32:继承 “站在巨人的肩膀上。” 继承是面向对象编程的三大特性之一(封装、继承、多态),它让我们可以基于已有类创建新类,实现代码复用。今天我们深入学习Python的继承机制。 1. 什么是继承 问题场景 假设要创建多个类: 1# 没有继承:代码重复 2class Dog: 3 def __init__(self, name, age): 4 self.name = name 5 self.age = age 6 7 def eat(self): 8 return f"{self.name} is eating" 9 10class Cat: 11 def __init__(self, name, age): 12 self.name = name 13 self.age = age 14 15 def eat(self): 16 return f"{self.name} is eating" 17 18 def meow(self): 19 return "Meow!" 20 21# 重复的代码... 继承(Inheritance): 子类继承父类的属性和方法 子类可以添加新的属性和方法 子类可以重写父类的方法 实现代码复用,减少重复 为什么需要继承: 代码复用:共享功能写一次 逻辑清晰:体现is-a关系(狗是动物) 易于维护:修改父类,所有子类受益 扩展性强:基于现有代码扩展新功能 继承的基本语法 1class ParentClass: 2 """父类(基类、超类)""" 3 pass 4 5class ChildClass(ParentClass): 6 """子类(派生类)""" 7 pass 2. 基本继承 简单示例 1class Animal: 2 """动物类(父类)""" 3 4 def __init__(self, name, age): 5 """初始化动物""" 6 self.name = name 7 self.age = age 8 9 def eat(self): 10 """吃东西(所有动物都会吃)""" 11 return f"{self.name} is eating" 12 13 def sleep(self): 14 """睡觉""" 15 return f"{self.name} is sleeping" 16 17class Dog(Animal): 18 """狗类(子类)- 继承Animal""" 19 20 def bark(self): 21 """狗叫(狗特有的方法)""" 22 return f"{self.name} says: Woof!" 23 24class Cat(Animal): 25 """猫类(子类)- 继承Animal""" 26 27 def meow(self): 28 """猫叫(猫特有的方法)""" 29 return f"{self.name} says: Meow!" 30 31# 使用 32dog = Dog("Buddy", 3) 33print(dog.eat()) # 继承自Animal:Buddy is eating 34print(dog.bark()) # Dog自己的方法:Buddy says: Woof! 35 36cat = Cat("Whiskers", 2) 37print(cat.eat()) # 继承自Animal:Whiskers is eating 38print(cat.meow()) # Cat自己的方法:Whiskers says: Meow! 继承的特点: ...

2025-05-10 · 6 min · 1135 words · 老墨

Python教程31:类与对象基础

Python教程31:类与对象基础 “万物皆对象。” 从今天开始,我们进入Python编程的新境界——面向对象编程(OOP)。这是一种组织代码的强大范式,让程序更贴近真实世界的思维方式。 1. 什么是面向对象编程 编程范式的演进 面向过程编程(Procedural Programming): 以函数为中心 数据和操作分离 适合简单问题 1# 面向过程:管理学生信息 2students = [ 3 {"name": "Alice", "age": 20, "grade": 85}, 4 {"name": "Bob", "age": 21, "grade": 90} 5] 6 7def calculate_average(students): 8 """计算平均成绩""" 9 total = sum(s["grade"] for s in students) 10 return total / len(students) 11 12# 数据和操作分离 面向对象编程(Object-Oriented Programming, OOP): 以对象为中心 数据和操作封装在一起 更贴近真实世界建模 1# 面向对象:学生类 2class Student: 3 """学生类:数据和行为封装在一起""" 4 def __init__(self, name, age, grade): 5 self.name = name 6 self.age = age 7 self.grade = grade 8 9 def get_info(self): 10 """学生的行为""" 11 return f"{self.name}, {self.age}岁, 成绩{self.grade}" 12 13# 创建对象 14alice = Student("Alice", 20, 85) 15bob = Student("Bob", 21, 90) OOP的核心概念 类(Class): ...

2025-04-17 · 5 min · 1004 words · 老墨

Python教程30:综合项目-任务管理器

Python教程30:综合项目-任务管理器 “纸上得来终觉浅,绝知此事要躬行。” 经过第三部分13课的学习,我们掌握了函数、模块、文件操作、异常处理、测试等核心知识。今天我们通过一个完整项目——命令行任务管理器,把这些知识综合应用起来。 1. 项目需求 功能需求 开发一个命令行任务管理器(Todo List),支持: 基本功能 添加任务 查看任务列表 标记任务完成 删除任务 进阶功能 任务优先级(高、中、低) 任务分类(工作、生活、学习) 截止日期 数据持久化(保存到文件) 额外功能 搜索任务 统计信息 导入/导出 技术要求 使用函数和类组织代码 模块化设计 完善的异常处理 文件操作(JSON格式存储) 单元测试 命令行交互 2. 项目结构 task_manager/ ├── task_manager/ # 主包 │ ├── __init__.py │ ├── task.py # 任务类 │ ├── manager.py # 管理器类 │ ├── storage.py # 存储模块 │ └── utils.py # 工具函数 ├── tests/ # 测试 │ ├── __init__.py │ ├── test_task.py │ ├── test_manager.py │ └── test_storage.py ├── main.py # 主程序入口 ├── README.md └── requirements.txt 3. 核心模块实现 3.1 任务类(task.py) 1""" 2任务类模块 3- 定义Task类表示单个任务 4- 应用:类、属性、方法 5""" 6 7from datetime import datetime 8from enum import Enum 9 10class Priority(Enum): 11 """ 12 任务优先级枚举 13 - 使用Enum定义常量 14 - 避免魔法数字 15 """ 16 LOW = 1 17 MEDIUM = 2 18 HIGH = 3 19 20class Category(Enum): 21 """任务分类""" 22 WORK = "工作" 23 LIFE = "生活" 24 STUDY = "学习" 25 OTHER = "其他" 26 27class Task: 28 """ 29 任务类 30 31 Attributes: 32 title: 任务标题 33 description: 任务描述 34 priority: 优先级 35 category: 分类 36 due_date: 截止日期 37 completed: 是否完成 38 created_at: 创建时间 39 """ 40 41 def __init__(self, title, description="", 42 priority=Priority.MEDIUM, 43 category=Category.OTHER, 44 due_date=None): 45 """ 46 初始化任务 47 48 Args: 49 title: 任务标题(必需) 50 description: 任务描述 51 priority: 优先级(默认中等) 52 category: 分类(默认其他) 53 due_date: 截止日期(datetime对象) 54 55 Raises: 56 ValueError: 标题为空时 57 """ 58 if not title: 59 raise ValueError("任务标题不能为空") 60 61 self.title = title 62 self.description = description 63 self.priority = priority 64 self.category = category 65 self.due_date = due_date 66 self.completed = False 67 self.created_at = datetime.now() 68 69 def mark_complete(self): 70 """标记任务完成""" 71 self.completed = True 72 73 def mark_incomplete(self): 74 """标记任务未完成""" 75 self.completed = False 76 77 def to_dict(self): 78 """ 79 转换为字典(用于JSON序列化) 80 81 Returns: 82 dict: 任务的字典表示 83 """ 84 return { 85 "title": self.title, 86 "description": self.description, 87 "priority": self.priority.value, 88 "category": self.category.value, 89 "due_date": self.due_date.isoformat() if self.due_date else None, 90 "completed": self.completed, 91 "created_at": self.created_at.isoformat() 92 } 93 94 @classmethod 95 def from_dict(cls, data): 96 """ 97 从字典创建任务(用于JSON反序列化) 98 99 Args: 100 data: 任务字典 101 102 Returns: 103 Task: 任务对象 104 """ 105 task = cls( 106 title=data["title"], 107 description=data.get("description", ""), 108 priority=Priority(data.get("priority", 2)), 109 category=Category(data.get("category", "其他")) 110 ) 111 112 if data.get("due_date"): 113 task.due_date = datetime.fromisoformat(data["due_date"]) 114 115 task.completed = data.get("completed", False) 116 task.created_at = datetime.fromisoformat(data["created_at"]) 117 118 return task 119 120 def __str__(self): 121 """字符串表示""" 122 status = "✓" if self.completed else " " 123 priority_symbols = { 124 Priority.LOW: "▽", 125 Priority.MEDIUM: "◇", 126 Priority.HIGH: "▲" 127 } 128 129 return f"[{status}] {priority_symbols[self.priority]} {self.title}" 130 131 def __repr__(self): 132 """开发者表示""" 133 return f"Task(title='{self.title}', completed={self.completed})" 3.2 存储模块(storage.py) 1""" 2存储模块 3- 负责任务数据的持久化 4- 应用:文件操作、JSON、异常处理 5""" 6 7import json 8import os 9from pathlib import Path 10from typing import List 11from task import Task 12 13class TaskStorage: 14 """ 15 任务存储类 16 - 使用JSON格式存储 17 - 包含完整的异常处理 18 """ 19 20 def __init__(self, file_path="tasks.json"): 21 """ 22 初始化存储 23 24 Args: 25 file_path: 存储文件路径 26 """ 27 self.file_path = Path(file_path) 28 self._ensure_file_exists() 29 30 def _ensure_file_exists(self): 31 """确保存储文件存在""" 32 if not self.file_path.exists(): 33 self.file_path.write_text("[]", encoding="utf-8") 34 35 def save_tasks(self, tasks: List[Task]): 36 """ 37 保存任务列表 38 39 Args: 40 tasks: 任务列表 41 42 Raises: 43 IOError: 文件写入失败时 44 """ 45 try: 46 data = [task.to_dict() for task in tasks] 47 48 # 使用with确保文件正确关闭 49 with open(self.file_path, "w", encoding="utf-8") as f: 50 json.dump(data, f, ensure_ascii=False, indent=2) 51 52 except Exception as e: 53 raise IOError(f"保存任务失败:{e}") 54 55 def load_tasks(self) -> List[Task]: 56 """ 57 加载任务列表 58 59 Returns: 60 List[Task]: 任务列表 61 62 Raises: 63 IOError: 文件读取失败时 64 """ 65 try: 66 with open(self.file_path, encoding="utf-8") as f: 67 data = json.load(f) 68 69 return [Task.from_dict(item) for item in data] 70 71 except json.JSONDecodeError as e: 72 raise IOError(f"JSON解析失败:{e}") 73 except Exception as e: 74 raise IOError(f"加载任务失败:{e}") 75 76 def backup(self, backup_path=None): 77 """ 78 备份任务数据 79 80 Args: 81 backup_path: 备份文件路径 82 """ 83 if backup_path is None: 84 backup_path = f"{self.file_path}.backup" 85 86 import shutil 87 shutil.copy(self.file_path, backup_path) 3.3 任务管理器(manager.py) 1""" 2任务管理器 3- 核心业务逻辑 4- 应用:类、方法、列表操作 5""" 6 7from typing import List, Optional 8from task import Task, Priority, Category 9from storage import TaskStorage 10 11class TaskManager: 12 """ 13 任务管理器 14 - 管理任务的CRUD操作 15 - 提供搜索、统计等功能 16 """ 17 18 def __init__(self, storage: TaskStorage): 19 """ 20 初始化管理器 21 22 Args: 23 storage: 存储对象 24 """ 25 self.storage = storage 26 self.tasks: List[Task] = [] 27 self.load() 28 29 def load(self): 30 """加载任务""" 31 try: 32 self.tasks = self.storage.load_tasks() 33 except IOError as e: 34 print(f"警告:{e}") 35 self.tasks = [] 36 37 def save(self): 38 """保存任务""" 39 try: 40 self.storage.save_tasks(self.tasks) 41 except IOError as e: 42 print(f"错误:{e}") 43 44 def add_task(self, task: Task): 45 """添加任务""" 46 self.tasks.append(task) 47 self.save() 48 49 def get_all_tasks(self) -> List[Task]: 50 """获取所有任务""" 51 return self.tasks 52 53 def get_task(self, index: int) -> Optional[Task]: 54 """ 55 获取指定任务 56 57 Args: 58 index: 任务索引 59 60 Returns: 61 Task或None 62 """ 63 if 0 <= index < len(self.tasks): 64 return self.tasks[index] 65 return None 66 67 def complete_task(self, index: int) -> bool: 68 """标记任务完成""" 69 task = self.get_task(index) 70 if task: 71 task.mark_complete() 72 self.save() 73 return True 74 return False 75 76 def delete_task(self, index: int) -> bool: 77 """删除任务""" 78 if 0 <= index < len(self.tasks): 79 self.tasks.pop(index) 80 self.save() 81 return True 82 return False 83 84 def search_tasks(self, keyword: str) -> List[Task]: 85 """ 86 搜索任务 87 88 Args: 89 keyword: 关键词 90 91 Returns: 92 匹配的任务列表 93 """ 94 keyword = keyword.lower() 95 return [ 96 task for task in self.tasks 97 if keyword in task.title.lower() 98 or keyword in task.description.lower() 99 ] 100 101 def get_statistics(self) -> dict: 102 """ 103 获取统计信息 104 105 Returns: 106 统计字典 107 """ 108 total = len(self.tasks) 109 completed = sum(1 for task in self.tasks if task.completed) 110 pending = total - completed 111 112 by_priority = { 113 Priority.HIGH: 0, 114 Priority.MEDIUM: 0, 115 Priority.LOW: 0 116 } 117 118 for task in self.tasks: 119 if not task.completed: 120 by_priority[task.priority] += 1 121 122 return { 123 "total": total, 124 "completed": completed, 125 "pending": pending, 126 "high_priority": by_priority[Priority.HIGH], 127 "medium_priority": by_priority[Priority.MEDIUM], 128 "low_priority": by_priority[Priority.LOW] 129 } 3.4 主程序(main.py) 1""" 2主程序入口 3- 命令行交互界面 4- 应用:函数、控制流程、异常处理 5""" 6 7from task import Task, Priority, Category 8from manager import TaskManager 9from storage import TaskStorage 10from datetime import datetime 11 12def print_menu(): 13 """打印菜单""" 14 print("\n" + "=" * 50) 15 print("任务管理器") 16 print("=" * 50) 17 print("1. 查看所有任务") 18 print("2. 添加任务") 19 print("3. 完成任务") 20 print("4. 删除任务") 21 print("5. 搜索任务") 22 print("6. 统计信息") 23 print("0. 退出") 24 print("=" * 50) 25 26def display_tasks(tasks): 27 """显示任务列表""" 28 if not tasks: 29 print("没有任务") 30 return 31 32 print("\n任务列表:") 33 for i, task in enumerate(tasks): 34 print(f"{i}. {task}") 35 if task.due_date: 36 print(f" 截止:{task.due_date.strftime('%Y-%m-%d')}") 37 38def add_task_interactive(manager: TaskManager): 39 """交互式添加任务""" 40 print("\n添加新任务") 41 42 title = input("标题:").strip() 43 if not title: 44 print("标题不能为空") 45 return 46 47 description = input("描述(可选):").strip() 48 49 print("优先级:1-低 2-中 3-高") 50 priority_input = input("选择(默认2):").strip() or "2" 51 priority = Priority(int(priority_input)) 52 53 try: 54 task = Task( 55 title=title, 56 description=description, 57 priority=priority 58 ) 59 manager.add_task(task) 60 print("✓ 任务已添加") 61 62 except ValueError as e: 63 print(f"错误:{e}") 64 65def main(): 66 """主函数""" 67 print("欢迎使用任务管理器") 68 69 # 初始化 70 storage = TaskStorage() 71 manager = TaskManager(storage) 72 73 while True: 74 print_menu() 75 choice = input("\n请选择操作:").strip() 76 77 try: 78 if choice == "1": 79 display_tasks(manager.get_all_tasks()) 80 81 elif choice == "2": 82 add_task_interactive(manager) 83 84 elif choice == "3": 85 display_tasks(manager.get_all_tasks()) 86 index = int(input("请输入任务编号:")) 87 if manager.complete_task(index): 88 print("✓ 任务已完成") 89 else: 90 print("无效的任务编号") 91 92 elif choice == "4": 93 display_tasks(manager.get_all_tasks()) 94 index = int(input("请输入任务编号:")) 95 if manager.delete_task(index): 96 print("✓ 任务已删除") 97 else: 98 print("无效的任务编号") 99 100 elif choice == "5": 101 keyword = input("请输入搜索关键词:") 102 results = manager.search_tasks(keyword) 103 display_tasks(results) 104 105 elif choice == "6": 106 stats = manager.get_statistics() 107 print(f"\n总任务数:{stats['total']}") 108 print(f"已完成:{stats['completed']}") 109 print(f"待完成:{stats['pending']}") 110 print(f" 高优先级:{stats['high_priority']}") 111 print(f" 中优先级:{stats['medium_priority']}") 112 print(f" 低优先级:{stats['low_priority']}") 113 114 elif choice == "0": 115 print("再见!") 116 break 117 118 else: 119 print("无效的选择") 120 121 except Exception as e: 122 print(f"发生错误:{e}") 123 import traceback 124 traceback.print_exc() 125 126if __name__ == "__main__": 127 main() 4. 单元测试 1# tests/test_task.py 2import unittest 3from datetime import datetime 4from task import Task, Priority, Category 5 6class TestTask(unittest.TestCase): 7 """测试Task类""" 8 9 def test_task_creation(self): 10 """测试任务创建""" 11 task = Task("测试任务") 12 13 self.assertEqual(task.title, "测试任务") 14 self.assertFalse(task.completed) 15 self.assertEqual(task.priority, Priority.MEDIUM) 16 17 def test_empty_title_raises_error(self): 18 """测试空标题抛出异常""" 19 with self.assertRaises(ValueError): 20 Task("") 21 22 def test_mark_complete(self): 23 """测试标记完成""" 24 task = Task("测试") 25 task.mark_complete() 26 27 self.assertTrue(task.completed) 28 29 def test_to_dict_and_from_dict(self): 30 """测试序列化/反序列化""" 31 task = Task("测试", priority=Priority.HIGH) 32 33 data = task.to_dict() 34 restored = Task.from_dict(data) 35 36 self.assertEqual(restored.title, task.title) 37 self.assertEqual(restored.priority, task.priority) 38 39if __name__ == "__main__": 40 unittest.main() 5. 知识点回顾 这个项目综合运用了: ...

2025-03-20 · 8 min · 1551 words · 老墨

Python教程29:函数与模块总结

Python教程29:函数与模块总结 “温故而知新,可以为师矣。” 经过前面13课的学习(第17-28课),我们系统学习了Python的函数、模块、异常处理等核心概念。今天我们回顾总结,梳理知识体系,巩固所学内容。 1. 函数基础回顾 核心概念 函数的作用: 代码复用:写一次,用多次 模块化:分解复杂问题 抽象:隐藏实现细节 可读性:函数名即文档 关键知识点 1# 基本结构 2def function_name(parameters): 3 """文档字符串""" 4 # 函数体 5 return result 6 7# 参数类型 8def func(a, b=默认值, *args, **kwargs): 9 """ 10 a: 位置参数 11 b: 默认参数 12 *args: 可变位置参数(元组) 13 **kwargs: 可变关键字参数(字典) 14 """ 15 pass 16 17# 返回值 18def multi_return(): 19 return value1, value2 # 实际返回元组 20 21# 函数是一等公民 22def outer(func): 23 return func # 可以作为参数和返回值 回顾第17课:函数基础(定义、参数、返回值、作用域) 2. Lambda与高阶函数 Lambda表达式 1# 匿名函数 2square = lambda x: x ** 2 3 4# 适用场景:简单、临时、作为参数 5sorted(students, key=lambda x: x["score"]) 高阶函数 1# map - 映射 2squares = map(lambda x: x**2, numbers) 3 4# filter - 过滤 5evens = filter(lambda x: x % 2 == 0, numbers) 6 7# reduce - 累积(需要从functools导入) 8from functools import reduce 9total = reduce(lambda x, y: x + y, numbers) 何时用Lambda vs普通函数: ...

2025-02-16 · 5 min · 904 words · 老墨

Python教程28:单元测试基础

Python教程28:单元测试基础 “测试不是万能的,但没有测试是万万不能的。” 代码写完了但不敢重构?担心修改一处就影响全局?单元测试能给你信心。今天我们学习Python的unittest模块,掌握自动化测试的基础。 1. 什么是单元测试 测试的重要性 为什么需要测试: 验证代码的正确性 防止回归(修改代码导致原有功能失效) 提高代码质量 便于重构(有测试保障) 作为文档(测试展示如何使用函数) 单元测试(Unit Test): 测试最小可测试单元(函数、方法、类) 独立运行,互不影响 快速执行 自动化 测试示例 待测试的代码: 1# calculator.py 2def add(a, b): 3 """加法""" 4 return a + b 5 6def divide(a, b): 7 """除法""" 8 if b == 0: 9 raise ValueError("除数不能为零") 10 return a / b 手动测试(不推荐): 1# 手动测试,繁琐且不可重复 2print(add(2, 3)) # 应该是5 3print(divide(10, 2)) # 应该是5 4# 每次修改代码都要手动运行... 自动化测试(推荐): 1# test_calculator.py 2import unittest 3from calculator import add, divide 4 5class TestCalculator(unittest.TestCase): 6 """ 7 测试用例类 8 - 继承unittest.TestCase 9 - 测试方法以test_开头 10 - 使用断言验证结果 11 """ 12 13 def test_add(self): 14 """测试加法""" 15 self.assertEqual(add(2, 3), 5) 16 self.assertEqual(add(-1, 1), 0) 17 18 def test_divide(self): 19 """测试除法""" 20 self.assertEqual(divide(10, 2), 5) 21 22 with self.assertRaises(ValueError): 23 divide(10, 0) 24 25if __name__ == "__main__": 26 unittest.main() 运行测试: ...

2025-02-07 · 5 min · 1059 words · 老墨

Python教程27:上下文管理器与with语句

Python教程27:上下文管理器与with语句 “始有终,开必合。” 我们已经多次使用with语句打开文件,今天深入学习它的原理——上下文管理器(Context Manager)。这是Python资源管理的利器,让代码更安全、更优雅。 1. 什么是上下文管理器 问题场景 资源(文件、网络连接、数据库连接、锁)需要正确管理: 1# 问题代码:可能忘记关闭 2file = open("data.txt") 3content = file.read() 4file.close() # 忘记关闭?异常时未关闭? 5 6# try-finally保证关闭 7file = open("data.txt") 8try: 9 content = file.read() 10finally: 11 file.close() # 总是执行 12 13# 但每次都这样写很繁琐... 上下文管理器(Context Manager): 自动管理资源的生命周期 确保资源的正确获取和释放 使用with语句 即使发生异常也能正确清理 1# with语句:简洁且安全 2with open("data.txt") as file: 3 content = file.read() 4# 自动关闭文件,即使有异常也会关闭 with语句的优势 自动清理:离开with块自动释放资源 异常安全:即使发生异常也会执行清理 代码简洁:不需要显式的try-finally 可读性强:明确表达资源管理意图 2. 上下文管理器协议 上下文管理器需要实现两个魔术方法: enter() 进入with块时调用,返回资源对象: 1def __enter__(self): 2 """ 3 进入上下文时调用 4 - 获取资源 5 - 返回的对象赋给as后的变量 6 """ 7 return self # 或其他资源对象 exit() 离开with块时调用,执行清理操作: ...

2025-01-26 · 5 min · 877 words · 老墨

Python教程26:异常处理

Python教程26:异常处理 “预则立,不预则废。” 程序运行时难免会遇到错误:文件不存在、网络断开、用户输入非法数据。异常处理机制让程序能够优雅地应对这些错误,而不是直接崩溃。今天我们学习Python的异常处理。 1. 什么是异常 错误vs异常 语法错误(Syntax Error): 代码写错了,Python无法解析 程序无法运行 例如:忘记冒号、括号不匹配 1# 语法错误示例 2if True # SyntaxError: 缺少冒号 3 print("Hello") 异常(Exception): 语法正确,但运行时出错 可以被捕获和处理 例如:除零、文件不存在、类型错误 1# 异常示例 2x = 1 / 0 # ZeroDivisionError: division by zero 为什么需要异常处理 没有异常处理: 1def divide(a, b): 2 return a / b 3 4result = divide(10, 0) # 程序崩溃! 5print("这行代码不会执行") 有异常处理: 1def divide(a, b): 2 try: 3 return a / b 4 except ZeroDivisionError: 5 print("错误:除数不能为0") 6 return None 7 8result = divide(10, 0) 9print("程序继续运行") # 这行会执行 异常处理的作用: 防止程序崩溃 提供友好的错误信息 执行清理操作(关闭文件、释放资源) 记录错误日志 优雅降级(功能不可用时提供备选方案) 2. 基本语法:try-except 1try: 2 # 可能出错的代码 3 risky_operation() 4except ExceptionType: 5 # 处理异常的代码 6 handle_error() 简单示例 1try: 2 num = int(input("请输入数字:")) 3 result = 10 / num 4 print(f"结果:{result}") 5except ValueError: 6 print("错误:请输入有效的数字") 7except ZeroDivisionError: 8 print("错误:除数不能为零") 执行流程: ...

2025-01-06 · 5 min · 921 words · 老墨

Python教程25:文件操作基础

Python教程25:文件操作基础 “磁盘是内存的延伸,文件是数据的归宿。” 程序经常需要读取配置文件、处理日志、保存数据。今天我们学习Python的文件操作,掌握数据持久化的基本技能。 1. 文件操作概述 为什么需要文件操作 内存vs文件: 内存(RAM):程序运行时的数据存储,速度快但程序结束后数据消失 文件(磁盘):永久存储数据,程序结束后数据保留 文件操作的应用场景: 读取配置文件(config.ini、settings.json) 处理日志文件(分析服务器日志) 数据持久化(保存用户数据) 批量处理(处理大量CSV、Excel文件) 网络爬虫(保存爬取的数据) Python文件操作的三个步骤 1# 1. 打开文件 2file = open("example.txt", "r") 3 4# 2. 读取/写入文件 5content = file.read() 6 7# 3. 关闭文件 8file.close() 为什么要关闭文件: 释放系统资源 确保数据完全写入磁盘 避免文件被锁定 防止内存泄漏 2. 打开文件:open()函数 open()是Python的内置函数,用于打开文件: 1# open(file, mode='r', encoding=None) 2# - file: 文件路径 3# - mode: 打开模式 4# - encoding: 编码格式(文本文件需要指定) 5 6file = open("data.txt", "r", encoding="utf-8") 文件模式 模式 说明 文件必须存在 覆盖内容 'r' 只读(默认) 是 - 'w' 只写 否(自动创建) 是 'a' 追加 否(自动创建) 否 'x' 独占创建 否(已存在报错) - 'r+' 读写 是 否 'w+' 读写 否(自动创建) 是 'a+' 读写追加 否(自动创建) 否 二进制模式:在模式后加'b' ...

2024-12-26 · 4 min · 827 words · 老墨

Python教程24:内置函数深入

Python教程24:内置函数深入 “工欲善其事,必先利其器。” Python提供了60多个内置函数(built-in functions),它们无需导入即可使用。今天我们深入学习最常用、最实用的内置函数,让你的代码更简洁高效。 1. 什么是内置函数 内置函数(Built-in Functions): Python解释器自带的函数 无需import即可直接使用 用C语言实现,性能优异 覆盖最常见的编程需求 查看所有内置函数: 1# dir(__builtins__)会列出所有内置对象 2# __builtins__是Python内置命名空间 3import builtins 4print(dir(builtins)) 5 6# 或者查看官方文档 7help(builtins) 我们已经用过很多内置函数:print()、len()、type()、int()、str()等。 2. 类型转换函数 基础类型转换 1# int() - 转换为整数 2# Python内置函数,将其他类型转为整数 3print(int("123")) # 123 4print(int(3.14)) # 3(截断小数部分) 5print(int("1010", 2)) # 10(二进制转十进制) 6print(int("FF", 16)) # 255(十六进制转十进制) 7 8# float() - 转换为浮点数 9print(float("3.14")) # 3.14 10print(float("inf")) # inf(无穷大) 11 12# str() - 转换为字符串 13print(str(123)) # "123" 14print(str([1, 2, 3])) # "[1, 2, 3]" 15 16# bool() - 转换为布尔值 17# 遵循Python的真值规则 18print(bool(0)) # False 19print(bool("")) # False 20print(bool([])) # False 21print(bool("False")) # True(非空字符串为True) 容器类型转换 1# list() - 转换为列表 2print(list("Python")) # ['P', 'y', 't', 'h', 'o', 'n'] 3print(list(range(5))) # [0, 1, 2, 3, 4] 4print(list({1, 2, 3})) # [1, 2, 3] 5 6# tuple() - 转换为元组 7print(tuple([1, 2, 3])) # (1, 2, 3) 8print(tuple("abc")) # ('a', 'b', 'c') 9 10# set() - 转换为集合(自动去重) 11print(set([1, 2, 2, 3, 3, 3])) # {1, 2, 3} 12print(set("hello")) # {'h', 'e', 'l', 'o'} 13 14# dict() - 转换为字典 15print(dict([('a', 1), ('b', 2)])) # {'a': 1, 'b': 2} 16print(dict(a=1, b=2)) # {'a': 1, 'b': 2} 3. 数学函数 1# abs() - 绝对值 2print(abs(-10)) # 10 3print(abs(-3.14)) # 3.14 4 5# round() - 四舍五入 6# 可以指定保留几位小数 7print(round(3.14159)) # 3 8print(round(3.14159, 2)) # 3.14 9print(round(3.14159, 3)) # 3.142 10 11# pow() - 幂运算 12# pow(x, y) 等价于 x ** y 13# pow(x, y, z) 等价于 (x ** y) % z(高效) 14print(pow(2, 3)) # 8 15print(pow(2, 3, 5)) # 3(即 8 % 5) 16 17# sum() - 求和 18# 可以指定起始值 19print(sum([1, 2, 3, 4, 5])) # 15 20print(sum([1, 2, 3], 10)) # 16(10 + 1 + 2 + 3) 21 22# min() / max() - 最小值/最大值 23print(min(1, 2, 3, 4, 5)) # 1 24print(max([1, 2, 3, 4, 5])) # 5 25print(min("apple", "banana")) # "apple"(字典序) 26 27# divmod() - 同时返回商和余数 28print(divmod(17, 5)) # (3, 2) 4. 序列操作函数 all() 和 any() 1#all() - 所有元素为True时返回True 2# Python内置函数,用于检查可迭代对象中所有元素 3print(all([True, True, True])) # True 4print(all([True, False, True])) # False 5print(all([])) # True(空序列) 6 7# 实际应用:检查所有数字是否为正数 8numbers = [1, 2, 3, 4, 5] 9print(all(n > 0 for n in numbers)) # True 10 11# any() - 任一元素为True时返回True 12print(any([False, False, True])) # True 13print(any([False, False, False])) # False 14print(any([])) # False(空序列) 15 16# 实际应用:检查是否含有偶数 17print(any(n % 2 == 0 for n in numbers)) # True sorted() 和 reversed() 1# sorted() - 排序(返回新列表) 2# 不修改原序列,返回排序后的新列表 3numbers = [3, 1, 4, 1, 5, 9, 2, 6] 4print(sorted(numbers)) # [1, 1, 2, 3, 4, 5, 6, 9] 5print(sorted(numbers, reverse=True)) # [9, 6, 5, 4, 3, 2, 1, 1] 6 7# 按长度排序 8words = ["python", "is", "awesome"] 9print(sorted(words, key=len)) # ['is', 'python', 'awesome'] 10 11# 按复杂规则排序 12students = [ 13 {"name": "Alice", "score": 85}, 14 {"name": "Bob", "score": 92}, 15 {"name": "Charlie", "score": 78} 16] 17print(sorted(students, key=lambda x: x["score"], reverse=True)) 18 19# reversed() - 反转(返回迭代器) 20print(list(reversed([1, 2, 3]))) # [3, 2, 1] 21print(list(reversed("Python"))) # ['n', 'o', 'h', 't', 'y', 'P'] zip() 和 enumerate() 1# zip() - 并行打包多个序列 2# Python内置函数,用于同时遍历多个序列 3names = ["Alice", "Bob", "Charlie"] 4ages = [25, 30, 35] 5cities = ["Beijing", "Shanghai", "Guangzhou"] 6 7# 打包成元组列表 8pairs = list(zip(names, ages, cities)) 9print(pairs) 10# [('Alice', 25, 'Beijing'), ('Bob', 30, 'Shanghai'), ('Charlie', 35, 'Guangzhou')] 11 12# 解包:zip的逆操作 13names2, ages2, cities2 = zip(*pairs) 14print(names2) # ('Alice', 'Bob', 'Charlie') 15 16# enumerate() - 带索引遍历 17# 返回(索引, 值)的元组 18for i, fruit in enumerate(["apple", "banana", "cherry"]): 19 print(f"{i}: {fruit}") 20 21# 指定起始索引 22for i, fruit in enumerate(["apple", "banana"], start=1): 23 print(f"{i}. {fruit}") 5. 高阶函数 map() 1# map() - 映射函数到序列 2# apply函数到每个元素,返回迭代器 3numbers = [1, 2, 3, 4, 5] 4 5# 平方 6squares = map(lambda x: x**2, numbers) 7print(list(squares)) # [1, 4, 9, 16, 25] 8 9# 字符串转大写 10words = ["hello", "world", "python"] 11upper_words = map(str.upper, words) 12print(list(upper_words)) # ['HELLO', 'WORLD', 'PYTHON'] 13 14# 多个序列 15a = [1, 2, 3] 16b = [4, 5, 6] 17sums = map(lambda x, y: x + y, a, b) 18print(list(sums)) # [5, 7, 9] filter() 1# filter() - 过滤序列 2# 保留使函数返回True的元素 3numbers = range(1, 11) 4 5# 过滤出偶数 6evens = filter(lambda x: x % 2 == 0, numbers) 7print(list(evens)) # [2, 4, 6, 8, 10] 8 9# 过滤空字符串 10strings = ["hello", "", "world", "", "python"] 11non_empty = filter(None, strings) # None会过滤掉假值 12print(list(non_empty)) # ['hello', 'world', 'python'] 6. 对象和属性函数 1# id() - 对象的唯一标识(内存地址) 2# Python内置函数,返回对象的身份标识 3a = [1, 2, 3] 4b = [1, 2, 3] 5print(id(a)) # 140234567890123(示例) 6print(id(b)) # 140234567890456(不同) 7print(id(a) == id(b)) # False 8 9# isinstance() - 类型检查 10print(isinstance(42, int)) # True 11print(isinstance("hello", str)) # True 12print(isinstance([1, 2], (list, tuple))) # True(多个类型) 13 14# hasattr() / getattr() / setattr() - 属性操作 15class Person: 16 def __init__(self, name): 17 self.name = name 18 19p = Person("Alice") 20print(hasattr(p, "name")) # True 21print(getattr(p, "name")) # "Alice" 22print(getattr(p, "age", 0)) # 0(默认值) 23setattr(p, "age", 25) 24print(p.age) # 25 25 26# dir() - 列出对象的所有属性和方法 27print(dir(str)) # 列出字符串的所有方法 7. 输入输出函数 1# print() -输出 2# sep参数:分隔符 3print("a", "b", "c", sep="-") # a-b-c 4 5# end参数:结束符(默认是换行) 6print("Hello", end=" ") 7print("World") # Hello World 8 9# file参数:输出到文件 10with open("output.txt", "w") as f: 11 print("Hello", file=f) 12 13# input() - 获取用户输入 14# 返回字符串,需要转换类型 15name = input("请输入姓名:") 16age = int(input("请输入年龄:")) 8. 编译和执行函数 1# eval() - 执行Python表达式字符串 2# 警告:不要对不可信的输入使用eval()! 3result = eval("1 + 2 * 3") 4print(result) # 7 5 6# exec() - 执行Python代码字符串 7code = """ 8def greet(name): 9 return f"Hello, {name}" 10print(greet("Alice")) 11""" 12exec(code) # 输出:Hello, Alice 13 14# compile() - 编译代码 15# 用于需要多次执行同一代码的场景 16code_obj = compile("1 + 2", "<string>", "eval") 17print(eval(code_obj)) # 3 安全警告:eval()和exec()很危险,不要对用户输入使用! ...

2024-11-22 · 5 min · 993 words · 老墨

Python教程23:迭代器(Iterator)

Python教程23:迭代器(Iterator) “万变不离其宗。” 我们已经用过很多次for循环,但你知道它背后的机制吗?今天我们学习迭代器(Iterator)——Python迭代的核心协议。 1. 什么是迭代器 可迭代对象vs迭代器 可迭代对象(Iterable): 可以用for循环遍历的对象 实现了__iter__()方法 例如:列表、元组、字典、字符串、生成器 迭代器(Iterator): 实现了__iter__()和__next__()方法的对象 可以被next()函数调用 记住当前位置,可以逐个返回元素 关系: 所有迭代器都是可迭代对象 但不是所有可迭代对象都是迭代器 可迭代对象调用iter()得到迭代器 1# 列表是可迭代对象,但不是迭代器 2my_list = [1, 2, 3] 3print(hasattr(my_list, '__iter__')) # True 4print(hasattr(my_list, '__next__')) # False 5 6# 获取迭代器 7iterator = iter(my_list) 8print(hasattr(iterator, '__iter__')) # True 9print(hasattr(iterator, '__next__')) # True 10 11# 使用迭代器 12print(next(iterator)) # 1 13print(next(iterator)) # 2 14print(next(iterator)) # 3 15# print(next(iterator)) # StopIteration 2. 迭代器协议 Python的迭代器协议包含两个方法: iter() 返回迭代器对象本身: 1class MyIterator: 2 def __iter__(self): 3 return self # 返回自己 作用: 让对象可以用于for循环 让对象可以调用iter() next() 返回下一个元素,没有元素时抛出StopIteration: 1class MyIterator: 2 def __next__(self): 3 # 返回下一个元素 4 # 或抛出StopIteration 5 pass 3. for循环的工作原理 for循环实际上是迭代器协议的语法糖: ...

2024-10-27 · 4 min · 797 words · 老墨

Python教程22:生成器(Generator)

Python教程22:生成器(Generator) “按需而生,用时即弃。” 生成器是Python中一个强大但常被忽视的特性。它能让你处理超大数据集而不耗尽内存,今天我们深入学习生成器的原理和应用。 1. 什么是生成器 问题场景 假设要生成1亿个数字: 1# 方法1:列表(占用大量内存) 2numbers = [i for i in range(100000000)] 3# 内存占用:约800MB! 4 5# 方法2:生成器(几乎不占内存) 6numbers = (i for i in range(100000000)) 7# 内存占用:几百字节 生成器(Generator): 一种特殊的迭代器 惰性求值:需要时才计算,不提前生成所有值 内存高效:一次只保存一个值 使用yield关键字或生成器表达式创建 为什么需要生成器: 处理大数据集(GB/TB级别) 无限序列(斐波那契数列、素数序列) 管道式数据处理 节省内存 2. 生成器函数 使用yield 普通函数用return返回值,生成器函数用yield: 1def simple_generator(): 2 """ 3 生成器函数示例 4 - yield关键字使函数变成生成器 5 - 每次yield都会"暂停"函数,保存状态 6 - 下次调用时从暂停处继续 7 """ 8 print("开始") 9 yield 1 10 print("继续") 11 yield 2 12 print("再继续") 13 yield 3 14 print("结束") 15 16# 创建生成器对象(还没执行函数体) 17gen = simple_generator() 18print(type(gen)) # <class 'generator'> 19 20# 每次调用next()执行到下一个yield 21print(next(gen)) # 输出:开始 1 22print(next(gen)) # 输出:继续 2 23print(next(gen)) # 输出:再继续 3 24# print(next(gen)) # StopIteration异常 yield的执行流程: ...

2024-10-14 · 4 min · 767 words · 老墨

Python教程21:包(Package)

Python教程21:包(Package) “治大国如烹小鲜,理大项目如分包装。” 上一课我们学习了模块,今天更进一步,学习包(Package)——模块的集合。当项目规模变大时,包能帮你更好地组织代码。 1. 什么是包 定义 **包(Package)**是一个包含__init__.py文件的目录,用于组织相关的模块。 为什么需要包: 层次化组织:大项目有上百个模块,需要分类 命名空间:不同包可以有同名模块 代码复用:打包分发给他人使用 团队协作:不同团队负责不同包 简单示例 项目结构: myproject/ ├── main.py └── utils/ # 这是一个包 ├── __init__.py # 必需!标识这是一个包 ├── string_utils.py └── math_utils.py init.py的作用: 告诉Python这个目录是一个包 可以为空文件 也可以包含包的初始化代码 Python 3.3+可以省略(但不推荐) 使用包: 1# main.py 2from utils import string_utils 3from utils import math_utils 4 5# 或者 6import utils.string_utils 7import utils.math_utils 2. 创建第一个包 步骤 创建目录结构: mymath/ ├── __init__.py ├── basic.py └── advanced.py 编写模块代码: 1# mymath/basic.py 2"""基础数学运算""" 3 4def add(a, b): 5 """加法""" 6 return a + b 7 8def subtract(a, b): 9 """减法""" 10 return a - b 1# mymath/advanced.py 2"""高级数学运算""" 3 4def power(base, exp): 5 """幂运算""" 6 return base ** exp 7 8def sqrt(x): 9 """平方根(简单实现)""" 10 return x ** 0.5 配置__init__.py: 1# mymath/__init__.py 2""" 3mymath包:提供数学运算功能 4 5这个文件在包被导入时执行,可以用来: 61. 初始化包级别的变量 72. 导入子模块,简化使用 83. 定义__all__,控制from package import *的行为 9""" 10 11# 包级别的变量 12VERSION = "1.0.0" 13 14# 简化导入:用户可以直接from mymath import add 15from .basic import add, subtract 16from .advanced import power, sqrt 17 18# 定义公开接口 19__all__ = ['add', 'subtract', 'power', 'sqrt', 'VERSION'] 20 21# 包初始化代码 22print(f"mymath包已加载,版本:{VERSION}") 使用包: 1# 方式1:直接从包导入(因为__init__.py中重新导出了) 2from mymath import add, power 3print(add(1, 2)) # 3 4print(power(2, 3)) # 8 5 6# 方式2:从子模块导入 7from mymath.basic import add 8from mymath.advanced import power 9 10# 方式3:导入整个包 11import mymath 12print(mymath.add(1, 2)) 13print(mymath.VERSION) 3. 子包和嵌套结构 包可以包含子包,形成层次结构: ...

2024-09-20 · 4 min · 671 words · 老墨

Python教程20:模块基础

Python教程20:模块基础 “分而治之,事半功倍。” 当代码越来越多时,把所有代码放在一个文件里会变得难以维护。模块(Module)就是Python的代码组织方式,让你可以把相关功能分门别类。今天我们学习如何创建和使用模块。 1. 什么是模块 定义 **模块(Module)**是一个包含Python代码的.py文件。每个Python文件都可以作为一个模块被其他文件导入使用。 为什么需要模块: 代码复用:写一次,到处用 命名空间:避免变量名冲突 代码组织:按功能分类,便于维护 协作开发:不同人负责不同模块 简单示例 创建一个文件math_utils.py: 1# math_utils.py 2"""数学工具模块""" 3 4PI = 3.14159 5 6def add(a, b): 7 """加法""" 8 return a + b 9 10def circle_area(radius): 11 """计算圆面积""" 12 return PI * radius ** 2 13 14class Calculator: 15 """计算器类""" 16 def multiply(self, a, b): 17 return a * b 在另一个文件中使用: 1# main.py 2import math_utils # 导入模块 3 4print(math_utils.PI) # 3.14159 5print(math_utils.add(3, 5)) # 8 6print(math_utils.circle_area(5)) # 78.53975 7 8calc = math_utils.Calculator() 9print(calc.multiply(4, 5)) # 20 模块的本质: 模块是一个命名空间(namespace) 文件名(去掉.py)就是模块名 通过模块名访问其中的变量、函数、类 2. 导入模块的方式 Python提供了多种导入方式,适应不同场景。 方式1:import模块名 1import math_utils 2 3# 使用:模块名.成员 4result = math_utils.add(1, 2) 优点: ...

2024-09-06 · 3 min · 554 words · 老墨

Python教程19:装饰器入门

Python教程19:装饰器入门 “简洁的力量在于抽象的恰当。” 装饰器是Python最强大的特性之一,也是初学者觉得最"神秘"的部分。今天我们从基础开始,逐步揭开装饰器的面纱,理解它的本质和应用。 1. 什么是装饰器 问题场景 假设你有多个函数,需要在每个函数执行前后记录日志: 1def add(a, b): 2 print("函数开始执行") # 重复代码 3 result = a + b 4 print("函数执行完毕") # 重复代码 5 return result 6 7def multiply(a, b): 8 print("函数开始执行") # 重复代码 9 result = a * b 10 print("函数执行完毕") # 重复代码 11 return result 问题:每个函数都要写重复的日志代码,违反了DRY(Don’t Repeat Yourself)原则。 装饰器的解决方案 装饰器是一种设计模式,用于在不修改原函数代码的情况下,给函数添加新功能。就像给礼物包装一样,外面包了一层,但礼物本身没变。 1@log_decorator # 这就是装饰器 2def add(a, b): 3 return a + b 4 5# 调用时自动有日志功能 6add(3, 5) 7# 输出: 8# 函数开始执行 9# 8 10# 函数执行完毕 2. 理解装饰器的基础:闭包 在学习装饰器前,需要先理解闭包(Closure)。 什么是闭包 闭包是指:一个函数内部定义的函数,可以访问外部函数的变量。 1def outer(x): 2 # x是外部函数的变量 3 4 def inner(y): 5 # inner可以访问outer的变量x 6 return x + y 7 8 return inner # 返回内部函数 9 10# 创建闭包 11add_5 = outer(5) 12print(add_5(3)) # 8(3 + 5) 13print(add_5(10)) # 15(10 + 5) 关键点: ...

2024-08-16 · 4 min · 775 words · 老墨

Python教程18:Lambda函数与高阶函数

Python教程18:Lambda函数与高阶函数 “简洁是智慧的灵魂。” Lambda函数是Python中一种简洁的函数定义方式,配合map、filter等高阶函数,能让代码更加优雅。今天我们学习函数式编程的基础。 1. Lambda函数基础 什么是Lambda Lambda是匿名函数,用于简单的单行函数: 1# 普通函数 2def square(x): 3 return x ** 2 4 5# Lambda函数 6square_lambda = lambda x: x ** 2 7 8print(square(5)) # 25 9print(square_lambda(5)) # 25 语法 1lambda 参数: 表达式 只能有一个表达式 自动返回表达式的值 不需要return 可以有多个参数 1# 多个参数 2add = lambda x, y: x + y 3print(add(3, 5)) # 8 4 5# 无参数 6greet = lambda: "Hello!" 7print(greet()) # Hello! 8 9# 默认参数 10power = lambda x, n=2: x ** n 11print(power(3)) # 9 12print(power(3, 3)) # 27 2. Lambda的实际应用 排序 1# 按元组第二个元素排序 2students = [ 3 ("Alice", 85), 4 ("Bob", 92), 5 ("Charlie", 78) 6] 7 8# 使用lambda 9students.sorted(key=lambda x: x[1], reverse=True) 10print(students) 11# [('Bob', 92), ('Alice', 85), ('Charlie', 78)] 12 13# 字典排序 14scores = {"Alice": 85, "Bob": 92, "Charlie": 78} 15sorted_scores = dict(sorted(scores.items(), key=lambda x: x[1], reverse=True)) 条件判断 1# 三元表达式 2max_val = lambda a, b: a if a > b else b 3print(max_val(10, 20)) # 20 4 5# 复杂条件 6grade = lambda score: 'A' if score >= 90 else ('B' if score >= 80 else 'C') 7print(grade(85)) # B 3. 高阶函数 高阶函数是接受函数作为参数或返回函数的函数。 ...

2024-08-07 · 3 min · 639 words · 老墨

Python教程17:函数基础

Python 教程 17:函数基础 “代码复用,从函数开始。” 函数是编程中最重要的概念之一。如果说变量是存储数据的容器,那函数就是执行任务的工具。掌握函数,你的代码将更加模块化、可维护、可复用。 1. 什么是函数 函数是一段可重复使用的代码块,用于完成特定任务。 1# 定义函数 2def greet(): 3 print("你好,世界!") 4 5# 调用函数 6greet() # 输出:你好,世界! 7greet() # 可以多次调用 为什么需要函数: 代码复用:写一次,用多次 模块化:把复杂问题分解 可维护:修改一处,处处生效 可读性:函数名即文档 2. 函数的定义 1def 函数名(参数列表): 2 """文档字符串""" 3 函数体 4 return 返回值 关键字: def:定义函数 函数名:遵循变量命名规则 参数列表:可选 return:返回值,可选 1# 最简单的函数 2def hello(): 3 print("Hello") 4 5# 带参数的函数 6def greet(name): 7 print(f"你好,{name}!") 8 9# 带返回值的函数 10def add(a, b): 11 return a + b 12 13# 完整的函数 14def calculate_area(radius): 15 """ 16 计算圆的面积 17 18 Args: 19 radius: 圆的半径 20 21 Returns: 22 圆的面积 23 """ 24 pi = 3.14159 25 return pi * radius ** 2 3. 函数的参数 位置参数 按顺序传递: ...

2024-07-05 · 3 min · 563 words · 老墨

Python教程16:数据结构综合实战

Python 教程 16:数据结构综合实战 “纸上得来终觉浅,绝知此事要躬行。” 学习了列表、元组、字典、集合后,让我们通过一个实际项目——学生成绩管理系统,把这些知识串起来,体会如何选择和组合不同的数据结构。 1. 项目需求 开发一个学生成绩管理系统,功能包括: 添加学生信息 录入和修改成绩 查询学生成绩 统计分析(平均分、最高分等) 筛选功能(如成绩优秀的学生) 2. 数据结构设计 方案选择 1# 学生信息:用字典 2student = { 3 "id": "2024001", 4 "name": "张三", 5 "age": 18, 6 "scores": { # 成绩:嵌套字典 7 "数学": 95, 8 "英语": 88, 9 "物理": 92 10 } 11} 12 13# 所有学生:用列表存储 14students = [ 15 {"id": "2024001", "name": "张三", "age": 18, "scores": {"数学": 95}}, 16 {"id": "2024002", "name": "李四", "age": 19, "scores": {"数学": 88}}, 17] 18 19# 学号索引:用字典加速查找 20students_by_id = { 21 "2024001": students[0], 22 "2024002": students[1], 23} 3. 核心功能实现 3.1 学生管理类 1class StudentManager: 2 """学生成绩管理系统""" 3 4 def __init__(self): 5 self.students = {} # {学号: 学生信息} 6 7 def add_student(self, student_id, name, age): 8 """添加学生""" 9 if student_id in self.students: 10 print(f"学号{student_id}已存在") 11 return False 12 13 self.students[student_id] = { 14 "id": student_id, 15 "name": name, 16 "age": age, 17 "scores": {} 18 } 19 print(f"✓ 添加学生:{name}") 20 return True 21 22 def add_score(self, student_id, subject, score): 23 """添加成绩""" 24 if student_id not in self.students: 25 print(f"学号{student_id}不存在") 26 return False 27 28 self.students[student_id]["scores"][subject] = score 29 print(f"✓ 录入成绩:{subject} = {score}") 30 return True 31 32 def get_student(self, student_id): 33 """查询学生信息""" 34 return self.students.get(student_id) 35 36 def get_average(self, student_id): 37 """计算学生平均分""" 38 student = self.get_student(student_id) 39 if not student or not student["scores"]: 40 return None 41 42 scores = student["scores"].values() 43 return sum(scores) / len(scores) 44 45 def get_top_students(self, n=5): 46 """获取成绩最好的N名学生""" 47 # 计算每个学生的平均分 48 student_avgs = [] 49 for sid, student in self.students.items(): 50 if student["scores"]: 51 avg = sum(student["scores"].values()) / len(student["scores"]) 52 student_avgs.append((student["name"], avg)) 53 54 # 排序并返回前N名 55 student_avgs.sort(key=lambda x: x[1], reverse=True) 56 return student_avgs[:n] 57 58 def get_subject_stats(self, subject): 59 """统计某科目的成绩分布""" 60 scores = [] 61 for student in self.students.values(): 62 if subject in student["scores"]: 63 scores.append(student["scores"][subject]) 64 65 if not scores: 66 return None 67 68 return { 69 "count": len(scores), 70 "max": max(scores), 71 "min": min(scores), 72 "avg": sum(scores) / len(scores) 73 } 74 75 def find_by_score_range(self, subject, min_score, max_score): 76 """查找某科目分数在指定范围内的学生""" 77 result = [] 78 for student in self.students.values(): 79 if subject in student["scores"]: 80 score = student["scores"][subject] 81 if min_score <= score <= max_score: 82 result.append({ 83 "name": student["name"], 84 "score": score 85 }) 86 return result 3.2 使用示例 1# 创建管理器 2manager = StudentManager() 3 4# 添加学生 5manager.add_student("2024001", "张三", 18) 6manager.add_student("2024002", "李四", 19) 7manager.add_student("2024003", "王五", 18) 8 9# 录入成绩 10manager.add_score("2024001", "数学", 95) 11manager.add_score("2024001", "英语", 88) 12manager.add_score("2024001", "物理", 92) 13 14manager.add_score("2024002", "数学", 87) 15manager.add_score("2024002", "英语", 94) 16manager.add_score("2024002", "物理", 89) 17 18manager.add_score("2024003", "数学", 92) 19manager.add_score("2024003", "英语", 85) 20manager.add_score("2024003", "物理", 95) 21 22# 查询学生 23student = manager.get_student("2024001") 24print(f"\n学生信息:{student['name']}") 25print(f"成绩:{student['scores']}") 26 27# 计算平均分 28avg = manager.get_average("2024001") 29print(f"平均分:{avg:.2f}") 30 31# 获取前3名 32print("\n前3名学生:") 33top_students = manager.get_top_students(3) 34for i, (name, avg) in enumerate(top_students, 1): 35 print(f"{i}. {name}: {avg:.2f}") 36 37# 统计数学成绩 38print("\n数学成绩统计:") 39stats = manager.get_subject_stats("数学") 40print(f"人数:{stats['count']}") 41print(f"最高分:{stats['max']}") 42print(f"最低分:{stats['min']}") 43print(f"平均分:{stats['avg']:.2f}") 44 45# 查找数学成绩90分以上的学生 46print("\n数学90分以上:") 47excellent = manager.find_by_score_range("数学", 90, 100) 48for item in excellent: 49 print(f"{item['name']}: {item['score']}") 4. 数据结构选择分析 为什么用字典存储学生 1# 方案1:列表(不推荐) 2students_list = [...] 3# 查找学生需要遍历:O(n) 4 5# 方案2:字典(推荐) 6students_dict = {"2024001": {...}} 7# 查找学生直接访问:O(1) 选择依据:需要频繁通过学号查找学生,字典更高效。 ...

2024-07-01 · 3 min · 633 words · 老墨

Python教程15:集合

Python 教程 15:集合 “世界上没有两片完全相同的树叶。” 集合(Set)是 Python 中一个特殊的数据结构,它最大的特点是元素唯一、无序。就像数学中的集合概念,非常适合去重和集合运算。 1. 什么是集合 集合是一个无序的、不重复的元素集合。 1# 创建集合 2empty_set = set() # 空集合(注意不是{}) 3numbers = {1, 2, 3, 4, 5} 4mixed = {1, "hello", 3.14, True} 5 6# 使用set()函数 7from_list = set([1, 2, 2, 3, 3, 3]) # {1, 2, 3}(自动去重) 8from_string = set("hello") # {'h', 'e', 'l', 'o'} 9 10# 集合推导式 11squares = {x**2 for x in range(5)} # {0, 1, 4, 9, 16} 注意:{}是空字典,不是空集合! 1empty_dict = {} 2empty_set = set() 3 4print(type(empty_dict)) # <class 'dict'> 5print(type(empty_set)) # <class 'set'> 2. 集合的基本操作 1fruits = {"苹果", "香蕉", "橙子"} 2 3# 添加元素 4fruits.add("葡萄") 5print(fruits) # {'苹果', '香蕉', '橙子', '葡萄'} 6 7# 添加多个元素 8fruits.update(["西瓜", "芒果"]) 9print(fruits) 10 11# 删除元素 12fruits.remove("香蕉") # 不存在会报错 13# fruits.remove("榴莲") # KeyError 14 15fruits.discard("橙子") # 不存在不报错 16fruits.discard("榴莲") # 不会报错 17 18# pop():randomly删除并返回一个元素 19item = fruits.pop() 20print(f"删除了:{item}") 21 22# clear():清空 23fruits.clear() 3. 集合运算 集合支持数学中的集合运算: ...

2024-06-04 · 3 min · 542 words · 老墨

Python教程14:字典基础

Python 教程 14:字典基础 “一把钥匙开一把锁。” 字典(Dictionary)是 Python 中最灵活、最强大的数据结构之一。它通过"键-值对"的方式存储数据,就像真实世界的字典用单词查释义一样。 1. 什么是字典 字典是一个无序的、可变的键值对集合。 1# 创建字典 2empty_dict = {} # 空字典 3user = { 4 "name": "张三", 5 "age": 25, 6 "city": "北京" 7} 8 9# 使用dict()函数 10from_pairs = dict([("a", 1), ("b", 2)]) 11from_keywords = dict(name="李四", age=30) 12 13# 字典推导式 14squares = {x: x**2 for x in range(5)} 15# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} 2. 访问字典 1user = {"name": "张三", "age": 25, "city": "北京"} 2 3# 方法1:[]访问 4print(user["name"]) # 张三 5# print(user["phone"]) # KeyError: 键不存在会报错 6 7# 方法2:get()方法(推荐) 8print(user.get("name")) # 张三 9print(user.get("phone")) # None(不报错) 10print(user.get("phone", "未设置")) # 未设置(默认值) 11 12# 检查键是否存在 13print("name" in user) # True 14print("phone" in user) # False 15print("phone" not in user) # True 3. 修改字典 1user = {"name": "张三", "age": 25} 2 3# 修改值 4user["age"] = 26 5print(user) # {'name': '张三', 'age': 26} 6 7# 添加键值对 8user["city"] = "上海" 9print(user) # {'name': '张三', 'age': 26, 'city': '上海'} 10 11# 删除键值对 12del user["city"] 13print(user) # {'name': '张三', 'age': 26} 14 15# pop():删除并返回值 16age = user.pop("age") 17print(age) # 26 18print(user) # {'name': '张三'} 19 20# popitem():删除并返回最后一个键值对(3.7+有序) 21user = {"a": 1, "b": 2, "c": 3} 22item = user.popitem() 23print(item) # ('c', 3) 4. 字典常用方法 获取键、值、项 1user = {"name": "张三", "age": 25, "city": "北京"} 2 3# keys():所有键 4print(user.keys()) # dict_keys(['name', 'age', 'city']) 5print(list(user.keys())) # ['name', 'age', 'city'] 6 7# values():所有值 8print(user.values()) # dict_values(['张三', 25, '北京']) 9print(list(user.values())) # ['张三', 25, '北京'] 10 11# items():所有键值对 12print(user.items()) 13# dict_items([('name', '张三'), ('age', 25), ('city', '北京')]) 14 15# 转换为列表 16items_list = list(user.items()) 17print(items_list) 18# [('name', '张三'), ('age', 25), ('city', '北京')] 更新和清空 1user = {"name": "张三", "age": 25} 2 3# update():更新字典 4user.update({"age": 26, "city": "北京"}) 5print(user) 6# {'name': '张三', 'age': 26, 'city': '北京'} 7 8# 也可以用关键字参数 9user.update(phone="13800138000") 10print(user) 11 12# clear():清空字典 13user.clear() 14print(user) # {} setdefault() 如果键存在,返回其值;否则设置默认值并返回: ...

2024-06-03 · 3 min · 607 words · 老墨

Python教程13:元组

Python 教程 13:元组 “不变,有时候是一种力量。” 元组和列表很像,但有一个关键区别:元组是不可变的。这个特性让元组在某些场景下比列表更安全、更高效。 1. 什么是元组 元组(Tuple)是一个有序的、不可变的元素集合。 1# 创建元组 2empty_tuple = () # 空元组 3single = (1,) # 单元素元组(注意逗号) 4numbers = (1, 2, 3, 4, 5) 5mixed = (1, "hello", 3.14, True) 6nested = ((1, 2), (3, 4)) 7 8# 也可以不用括号(但不推荐) 9point = 10, 20 10print(point) # (10, 20) 11 12# 使用tuple()函数 13from_list = tuple([1, 2, 3]) 14from_string = tuple("Python") # ('P', 'y', 't', 'h', 'o', 'n') 注意:单元素元组必须有逗号! 1not_a_tuple = (1) # 这是整数1 2is_a_tuple = (1,) # 这才是元组 2. 访问元组元素 元组的访问方式和列表完全相同: 1fruits = ("苹果", "香蕉", "橙子", "葡萄") 2 3# 索引 4print(fruits[0]) # 苹果 5print(fruits[-1]) # 葡萄 6 7# 切片 8print(fruits[1:3]) # ('香蕉', '橙子') 9print(fruits[::-1]) # ('葡萄', '橙子', '香蕉', '苹果') 10 11# 遍历 12for fruit in fruits: 13 print(fruit) 14 15# enumerate 16for i, fruit in enumerate(fruits): 17 print(f"{i}: {fruit}") 3. 元组的不可变性 元组创建后不能修改: ...

2024-05-21 · 3 min · 547 words · 老墨

Python教程12:列表进阶与推导式高级

Python教程12:列表进阶与推导式高级 “熟能生巧,巧能生精。” 在第8课我们学习了列表推导式的基础,今天我们深入探讨列表推导式的高级技巧和列表的进阶操作,让你的代码更加Pythonic和高效。 1. 回顾:列表推导式基础 1# 基础语法 2squares = [x**2 for x in range(10)] 3 4# 带条件 5evens = [x for x in range(10) if x % 2 == 0] 6 7# if-else 8result = [x if x > 0 else 0 for x in [-1, 2, -3, 4]] 2. 嵌套列表推导式 二维列表展平 1# 传统方法 2matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 3flat = [] 4for row in matrix: 5 for num in row: 6 flat.append(num) 7 8# 列表推导式 9flat = [num for row in matrix for num in row] 10print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9] 理解技巧:从左到右阅读,就像嵌套的for循环。 创建二维列表 1# 创建3×3矩阵 2matrix = [[0 for _ in range(3)] for _ in range(3)] 3print(matrix) 4# [[0, 0, 0], [0, 0, 0], [0, 0, 0]] 5 6# 创建乘法表 7table = [[i*j for j in range(1, 10)] for i in range(1, 10)] 8 9# 注意:不要这样创建二维列表 10# bad = [[0] * 3] * 3 # 错误!所有行是同一个对象 多重嵌套with条件 1# 找出两个列表的所有组合(有条件) 2a = [1, 2, 3] 3b = [3, 4, 5] 4 5# 找出和大于5的组合 6result = [(x, y) for x in a for y in b if x + y > 5] 7print(result) # [(2, 4), (2, 5), (3, 3), (3, 4), (3, 5)] 3. 列表推导式vs传统循环 1# 性能对比示例 2import time 3 4# 方法1:传统for循环 5start = time.time() 6result1 = [] 7for i in range(100000): 8 result1.append(i**2) 9time1 = time.time() - start 10 11# 方法2:列表推导式 12start = time.time() 13result2 = [i**2 for i in range(100000)] 14time2 = time.time() - start 15 16print(f"传统循环:{time1:.4f}秒") 17print(f"列表推导式:{time2:.4f}秒") 18# 列表推导式通常快20-30% 4. 字典和集合推导式进阶 字典推导式高级用法 1# 统计字符出现次数 2text = "hello world" 3char_count = {char: text.count(char) for char in set(text) if char != ' '} 4 5# 从列表创建索引字典 6fruits = ['apple', 'banana', 'cherry'] 7fruit_index = {fruit: i for i, fruit in enumerate(fruits)} 8 9# 嵌套字典推导式 10students = ['Alice', 'Bob'] 11subjects = ['Math', 'English'] 12grades = { 13 student: {subject: 0 for subject in subjects} 14 for student in students 15} 集合推导式妙用 1# 去重并转换 2numbers = [1, -2, 3, -4, 5] 3abs_unique = {abs(n) for n in numbers} # {1, 2, 3, 4, 5} 4 5# 找差异 6list1 = [1, 2, 3, 4, 5] 7list2 = [4, 5, 6, 7, 8] 8diff = {x for x in list1 if x not in list2} # {1, 2, 3} 5. 生成器表达式深入 1# 列表推导式:立即生成,占内存 2squares_list = [x**2 for x in range(1000000)] 3 4# 生成器表达式:按需生成,省内存 5squares_gen = (x**2 for x in range(1000000)) 6 7# 使用生成器 8total = sum(x**2 for x in range(1000000)) 9 10# 生成器只能遍历一次 11gen = (x for x in range(5)) 12print(list(gen)) # [0, 1, 2, 3, 4] 13print(list(gen)) # [](已耗尽) 6. 列表的高级操作 zip和enumerate进阶 1# zip并行遍历 2names = ['Alice', 'Bob', 'Charlie'] 3ages = [25, 30, 35] 4cities = ['Beijing', 'Shanghai', 'Guangzhou'] 5 6# 创建字典 7people = [ 8 {'name': n, 'age': a, 'city': c} 9 for n, a, c in zip(names, ages, cities) 10] 11 12# enumerate with start 13for i, name in enumerate(names, start=1): 14 print(f"{i}. {name}") filter和map结合推导式 1# 虽然有filter和map,但推导式更清晰 2numbers = range(1, 11) 3 4# filter + map方式 5result1 = list(map(lambda x: x**2, filter(lambda x: x % 2 == 0, numbers))) 6 7# 推导式方式(更清晰) 8result2 = [x**2 for x in numbers if x % 2 == 0] 7. 实战案例 案例1:矩阵转置 1matrix = [ 2 [1, 2, 3], 3 [4, 5, 6], 4 [7, 8, 9] 5] 6 7# 转置 8transposed = [[row[i] for row in matrix] for i in range(len(matrix[0]))] 9print(transposed) 10# [[1, 4, 7], [2, 5, 8], [3, 6, 9]] 11 12# 或使用zip 13transposed = [list(col) for col in zip(*matrix)] 案例2:笛卡尔积 1colors = ['红', '黑'] 2sizes = ['S', 'M', 'L'] 3products = [f"{color}-{size}" for color in colors for size in sizes] 4# ['红-S', '红-M', '红-L', '黑-S', '黑-M', '黑-L'] 案例3:数据清洗 1# 清洗CSV数据 2raw_data = [ 3 " Alice, 25 ", 4 "Bob,30", 5 " Charlie, 35 " 6] 7 8cleaned = [ 9 [item.strip() for item in row.split(',')] 10 for row in raw_data 11] 8. 何时不用推导式 虽然推导式简洁,但有时不适合: ...

2024-04-28 · 4 min · 744 words · 老墨

Python教程11:列表基础

Python教程11:列表基础 “工欲善其事,必先利其器。” 列表(List)是Python中最常用的数据结构之一,就像一个可以随意增删改查的购物清单。今天我们深入学习列表的基础操作,为后续学习打好基础。 1. 什么是列表 列表是一个有序的、可变的元素集合,可以存储不同类型的数据。 1# 创建列表 2empty_list = [] # 空列表 3numbers = [1, 2, 3, 4, 5] # 整数列表 4mixed = [1, "hello", 3.14, True] # 混合类型 5nested = [[1, 2], [3, 4], [5, 6]] # 嵌套列表 6 7# 使用list()函数 8from_string = list("Python") # ['P', 'y', 't', 'h', 'o', 'n'] 9from_range = list(range(5)) # [0, 1, 2, 3, 4] 2. 访问列表元素 索引访问 1fruits = ["苹果", "香蕉", "橙子", "葡萄", "西瓜"] 2 3# 正向索引(从0开始) 4print(fruits[0]) # 苹果 5print(fruits[1]) # 香蕉 6 7# 负向索引(从-1开始) 8print(fruits[-1]) # 西瓜(最后一个) 9print(fruits[-2]) # 葡萄(倒数第二个) 10 11# 索引越界会报错 12# print(fruits[10]) # IndexError 切片访问 1numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 3# [start:stop:step] 4print(numbers[2:5]) # [2, 3, 4] 5print(numbers[:5]) # [0, 1, 2, 3, 4] 6print(numbers[5:]) # [5, 6, 7, 8, 9] 7print(numbers[::2]) # [0, 2, 4, 6, 8](步长为2) 8print(numbers[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0](反转) 9 10# 负索引切片 11print(numbers[-3:]) # [7, 8, 9] 12print(numbers[:-3]) # [0, 1, 2, 3, 4, 5, 6] 3. 修改列表 列表是可变的,可以直接修改元素: ...

2024-04-15 · 4 min · 750 words · 老墨

Python教程10:第一个实用程序

Python 教程 10:第一个实用程序 “纸上得来终觉浅,绝知此事要躬行。” 经过前面 9 课的学习,我们已经掌握了 Python 的基础知识。今天,让我们把这些知识串起来,开发一个真正实用的程序:批量文件重命名工具。 1. 项目需求 开发一个命令行工具,能够: 批量重命名文件:支持添加前缀、后缀、替换文本 过滤文件:支持按扩展名、文件名模式过滤 预览模式:先预览修改,确认后再执行 撤销功能:记录操作,支持撤销 这个工具很实用,能解决日常工作中的真实问题。 2. 项目结构 file_renamer/ ├── file_renamer.py # 主程序 ├── renamer.py # 核心重命名逻辑 ├── utils.py # 工具函数 └── history.json # 操作历史记录 3. 核心功能实现 3.1 列出目录中的文件 1# utils.py 2import os 3 4def list_files(directory, extension=None, pattern=None): 5 """ 6 列出目录中的文件 7 8 Args: 9 directory: 目标目录 10 extension: 文件扩展名过滤(如'.txt') 11 pattern: 文件名模式(简单的包含匹配) 12 13 Returns: 14 文件路径列表 15 """ 16 files = [] 17 18 for filename in os.listdir(directory): 19 filepath = os.path.join(directory, filename) 20 21 # 只处理文件,忽略目录 22 if not os.path.isfile(filepath): 23 continue 24 25 # 扩展名过滤 26 if extension and not filename.endswith(extension): 27 continue 28 29 # 文件名模式过滤 30 if pattern and pattern not in filename: 31 continue 32 33 files.append(filepath) 34 35 return files 3.2 重命名逻辑 1# renamer.py 2import os 3import re 4 5class FileRenamer: 6 """文件重命名器""" 7 8 def __init__(self, directory): 9 self.directory = directory 10 self.changes = [] # 记录修改 11 12 def add_prefix(self, files, prefix): 13 """添加前缀""" 14 for filepath in files: 15 dirname = os.path.dirname(filepath) 16 filename = os.path.basename(filepath) 17 new_name = prefix + filename 18 new_path = os.path.join(dirname, new_name) 19 self.changes.append((filepath, new_path)) 20 21 def add_suffix(self, files, suffix): 22 """添加后缀(在扩展名前)""" 23 for filepath in files: 24 dirname = os.path.dirname(filepath) 25 filename = os.path.basename(filepath) 26 name, ext = os.path.splitext(filename) 27 new_name = name + suffix + ext 28 new_path = os.path.join(dirname, new_name) 29 self.changes.append((filepath, new_path)) 30 31 def replace_text(self, files, old_text, new_text): 32 """替换文件名中的文本""" 33 for filepath in files: 34 dirname = os.path.dirname(filepath) 35 filename = os.path.basename(filepath) 36 new_name = filename.replace(old_text, new_text) 37 new_path = os.path.join(dirname, new_name) 38 if filepath != new_path: # 只记录有变化的 39 self.changes.append((filepath, new_path)) 40 41 def preview(self): 42 """预览修改""" 43 if not self.changes: 44 print("没有要修改的文件") 45 return 46 47 print(f"\n将要进行 {len(self.changes)} 项修改:") 48 print("-" * 60) 49 for i, (old, new) in enumerate(self.changes, 1): 50 old_name = os.path.basename(old) 51 new_name = os.path.basename(new) 52 print(f"{i}. {old_name} -> {new_name}") 53 print("-" * 60) 54 55 def execute(self): 56 """执行重命名""" 57 if not self.changes: 58 print("没有要执行的操作") 59 return 60 61 success_count = 0 62 for old_path, new_path in self.changes: 63 try: 64 os.rename(old_path, new_path) 65 success_count += 1 66 except Exception as e: 67 print(f"错误:{old_path} -> {e}") 68 69 print(f"\n成功重命名 {success_count}/{len(self.changes)} 个文件") 70 71 # 保存操作历史 72 self.save_history() 73 74 def save_history(self): 75 """保存操作历史(简化版)""" 76 import json 77 from datetime import datetime 78 79 history_file = "history.json" 80 81 # 读取现有历史 82 history = [] 83 if os.path.exists(history_file): 84 with open(history_file, 'r', encoding='utf-8') as f: 85 history = json.load(f) 86 87 # 添加新记录 88 history.append({ 89 'time': datetime.now().isoformat(), 90 'changes': [(old, new) for old, new in self.changes] 91 }) 92 93 # 保存 94 with open(history_file, 'w', encoding='utf-8') as f: 95 json.dump(history, f, indent=2, ensure_ascii=False) 3.3 主程序 1# file_renamer.py 2#!/usr/bin/env python3 3# -*- coding: utf-8 -*- 4 5""" 6文件批量重命名工具 7 8用法: 9 python file_renamer.py 10""" 11 12import os 13from renamer import FileRenamer 14from utils import list_files 15 16def main(): 17 print("=" * 60) 18 print("文件批量重命名工具") 19 print("=" * 60) 20 21 # 获取目录 22 directory = input("\n请输入目录路径(留空使用当前目录):").strip() 23 if not directory: 24 directory = "." 25 26 if not os.path.exists(directory): 27 print(f"错误:目录 '{directory}' 不存在") 28 return 29 30 # 获取文件过滤条件 31 extension = input("文件扩展名过滤(如.txt,留空跳过):").strip() 32 if not extension: 33 extension = None 34 35 # 列出文件 36 files = list_files(directory, extension) 37 38 if not files: 39 print("没有找到符合条件的文件") 40 return 41 42 print(f"\n找到 {len(files)} 个文件") 43 44 # 创建重命名器 45 renamer = FileRenamer(directory) 46 47 # 操作菜单 48 while True: 49 print("\n请选择操作:") 50 print("1. 添加前缀") 51 print("2. 添加后缀") 52 print("3. 替换文本") 53 print("4. 预览修改") 54 print("5. 执行重命名") 55 print("0. 退出") 56 57 choice = input("\n请输入选择:").strip() 58 59 if choice == "1": 60 prefix = input("请输入前缀:") 61 renamer.add_prefix(files, prefix) 62 print("✓ 已添加前缀规则") 63 64 elif choice == "2": 65 suffix = input("请输入后缀:") 66 renamer.add_suffix(files, suffix) 67 print("✓ 已添加后缀规则") 68 69 elif choice == "3": 70 old_text = input("请输入要替换的文本:") 71 new_text = input("请输入新文本:") 72 renamer.replace_text(files, old_text, new_text) 73 print("✓ 已添加替换规则") 74 75 elif choice == "4": 76 renamer.preview() 77 78 elif choice == "5": 79 renamer.preview() 80 confirm = input("\n确认执行?(y/N):").strip().lower() 81 if confirm == 'y': 82 renamer.execute() 83 break 84 else: 85 print("已取消") 86 87 elif choice == "0": 88 print("再见!") 89 break 90 91 else: 92 print("无效的选择") 93 94if __name__ == "__main__": 95 main() 4. 使用示例 场景 1:照片重命名 假设有一批照片: ...

2024-03-18 · 4 min · 787 words · 老墨

Python教程09:Python编码规范(PEP 8)

Python 教程 09:Python 编码规范(PEP 8) “代码的阅读次数远远多于编写次数。” PEP 8 是 Python 官方的编码规范,定义了如何写出"Pythonic"的代码。遵循这些规范,你的代码会更专业、更易读、更容易被其他 Python 程序员理解。 1. 什么是 PEP 8 PEP (Python Enhancement Proposal) 是 Python 增强提案。PEP 8 专门定义了 Python 代码的风格指南。 核心思想: 代码更多是被阅读,而不是被编写 一致性很重要 可读性至上 完整文档:https://peps.python.org/pep-0008/ 2. 缩进和空格 使用 4 个空格缩进 1# 正确 2def hello(): 3 print("Hello") 4 if True: 5 print("World") 6 7# 错误:使用Tab或2个空格 8def hello(): 9 print("Hello") # 2个空格,不推荐 续行对齐 1# 方法1:对齐左括号 2result = some_function(argument1, argument2, 3 argument3, argument4) 4 5# 方法2:悬挂缩进 6result = some_function( 7 argument1, argument2, 8 argument3, argument4 9) 10 11# 列表、字典的续行 12my_list = [ 13 1, 2, 3, 14 4, 5, 6, 15] # 末尾逗号是好习惯 3. 空行 类和函数之间 1# 顶层函数和类之间空2行 2def function1(): 3 pass 4 5 6def function2(): 7 pass 8 9 10class MyClass: 11 pass 12 13 14class AnotherClass: 15 pass 方法之间 1class MyClass: 2 # 类中的方法之间空1行 3 def method1(self): 4 pass 5 6 def method2(self): 7 pass 函数内部逻辑分组 1def complex_function(): 2 # 初始化部分 3 x = 10 4 y = 20 5 6 # 计算部分 7 result = x + y 8 9 # 返回结果 10 return result 4. 最大行长度 每行不超过 79 个字符(文档字符串/注释不超过 72 个字符)。 ...

2024-03-02 · 4 min · 748 words · 老墨

Python教程08:列表推导式入门

Python 教程 08:列表推导式入门 “简洁是智慧的灵魂。” —— 莎士比亚 列表推导式是 Python 最具特色的语法之一,它让你用一行代码完成原本需要多行循环才能实现的功能。这不仅是代码的简化,更是思维方式的提升。 1. 什么是列表推导式 列表推导式(List Comprehension)是一种简洁的创建列表的方式。 传统方法: 1# 生成1-10的平方 2squares = [] 3for i in range(1, 11): 4 squares.append(i ** 2) 5print(squares) # [1, 4, 9, 16, ..., 100] 列表推导式: 1# 一行搞定 2squares = [i ** 2 for i in range(1, 11)] 3print(squares) # [1, 4, 9, 16, ..., 100] 代码从 3 行变成 1 行,清晰简洁,这就是 Python 的魅力。 2. 基本语法 1[表达式 for 变量 in 序列] 执行过程: 遍历序列中的每个元素 将元素赋值给变量 计算表达式 将结果添加到新列表 1# 示例 2numbers = [1, 2, 3, 4, 5] 3 4# 每个数乘以2 5doubled = [n * 2 for n in numbers] 6print(doubled) # [2, 4, 6, 8, 10] 7 8# 转换为字符串 9str_list = [str(n) for n in numbers] 10print(str_list) # ['1', '2', '3', '4', '5'] 11 12# 调用方法 13names = ['alice', 'bob', 'charlie'] 14capitalized = [name.capitalize() for name in names] 15print(capitalized) # ['Alice', 'Bob', 'Charlie'] 3. 带条件的列表推导式 可以添加 if 条件进行过滤: ...

2024-02-28 · 4 min · 816 words · 老墨

Python教程07:字符串深入

Python 教程 07:字符串深入 “语言是思维的外壳。” 字符串是编程中最常用的数据类型之一,几乎每个程序都要处理文本。今天我们深入学习 Python 字符串的各种操作,从格式化到正则表达式,让你处理文本得心应手。 1. 字符串的创建 Python 中创建字符串有多种方式: 1# 单引号 2s1 = 'Hello' 3 4# 双引号 5s2 = "World" 6 7# 三引号(多行字符串) 8s3 = """这是一个 9多行 10字符串""" 11 12s4 = '''也可以用 13单引号''' 14 15# 原始字符串(忽略转义字符) 16path = r"C:\Users\name\documents" # \n不会被解释为换行 17 18# 字符串拼接 19full = s1 + " " + s2 # "Hello World" 2. 字符串格式化:三种武器 方法 1:%格式化(老式,不推荐) 1name = "张三" 2age = 25 3print("我叫%s,今年%d岁" % (name, age)) 4 5# 格式控制 6pi = 3.14159 7print("π = %.2f" % pi) # 保留2位小数 方法 2:format()方法 1# 位置参数 2print("{}+{}={}".format(1, 2, 3)) 3 4# 索引 5print("{0}+{1}={2}".format(1, 2, 3)) 6print("{2}+{1}={0}".format(3, 2, 1)) # 调换顺序 7 8# 关键字参数 9print("{name}今年{age}岁".format(name="李四", age=30)) 10 11# 格式控制 12print("{:.2f}".format(3.14159)) # 3.14 13print("{:0>5}".format(42)) # 00042(左侧填充0,总宽度5) 14print("{:*^10}".format("Hi")) # ****Hi****(居中,宽度10,填充*) 方法 3:f-string(Python 3.6+,最推荐) 1name = "王五" 2age = 28 3city = "北京" 4 5# 简洁直观 6print(f"{name}今年{age}岁,来自{city}") 7 8# 表达式 9print(f"明年我{age + 1}岁") 10print(f"2的10次方是{2 ** 10}") 11 12# 格式控制 13pi = 3.14159 14print(f"π ≈ {pi:.2f}") 15 16# 对齐和填充 17num = 42 18print(f"{num:0>5}") # 00042 19print(f"{num:*^10}") # ****42**** 20 21# 调试输出(Python 3.8+) 22x = 10 23print(f"{x=}") # x=10 推荐:新代码统一使用 f-string,简洁且高效。 ...

2024-02-27 · 3 min · 622 words · 老墨

Python教程06:控制流程-循环语句

Python 教程 06:控制流程-循环语句 “重复是力量之母。” 如果说条件语句让程序会"选择",那循环语句就让程序会"重复"。想象一下,如果要打印 1 到 100 的数字,难道要写 100 行print()吗?循环语句就是为了解决这类重复性工作而生的。 1. for 循环:遍历序列 for 循环用于遍历序列(列表、字符串、范围等)中的每个元素。 基本语法 1# 遍历列表 2fruits = ["苹果", "香蕉", "橙子"] 3for fruit in fruits: 4 print(f"我喜欢吃{fruit}") 5 6# 遍历字符串 7for char in "Python": 8 print(char) 9 10# 遍历字典 11user = {"name": "张三", "age": 25, "city": "北京"} 12for key in user: 13 print(f"{key}: {user[key]}") 语法要点: for 变量 in 序列: 循环体必须缩进 每次循环,变量会依次取序列中的每个值 range()函数 range()生成数字序列,是 for 循环的好搭档。 1# range(stop):从0到stop-1 2for i in range(5): 3 print(i) # 0, 1, 2, 3, 4 4 5# range(start, stop):从start到stop-1 6for i in range(1, 6): 7 print(i) # 1, 2, 3, 4, 5 8 9# range(start, stop, step):指定步长 10for i in range(0, 10, 2): 11 print(i) # 0, 2, 4, 6, 8 12 13# 倒序 14for i in range(10, 0, -1): 15 print(i) # 10, 9, 8, ..., 1 enumerate():带索引的遍历 有时候需要同时获取元素和索引: ...

2024-01-21 · 4 min · 687 words · 老墨

Python教程05:控制流程-条件语句

Python 教程 05:控制流程-条件语句 “人生处处是选择。” 程序和人生一样,也需要做出选择。条件语句就是让程序具备"决策"能力的工具,就像十字路口的红绿灯,告诉你该往哪走。 1. if 语句:单向选择 最简单的条件语句,满足条件就执行,不满足就跳过。 1age = 20 2 3if age >= 18: 4 print("你已经成年了") 5 print("可以独立做决定") 语法要点: if后面跟条件表达式,以冒号结尾 条件代码块必须缩进(通常 4 个空格) 缩进的代码属于 if 块,一起执行或跳过 2. if-else:双向选择 两条路,必须选一条。 1age = 15 2 3if age >= 18: 4 print("成年人,可以投票") 5else: 6 print("未成年,不能投票") 就像走到岔路口,往左或往右,总要选一个方向。 3. if-elif-else:多向选择 当选择超过两个时,使用elif(else if 的缩写)。 1score = 85 2 3if score >= 90: 4 grade = "A" 5elif score >= 80: 6 grade = "B" 7elif score >= 70: 8 grade = "C" 9elif score >= 60: 10 grade = "D" 11else: 12 grade = "F" 13 14print(f"分数:{score},等级:{grade}") 执行顺序: 从上到下依次判断 遇到第一个为 True 的条件就执行,然后跳出整个 if-elif-else 结构 如果所有条件都是 False,执行 else 块(如果有的话) 这就像走迷宫,找到第一个出口就出去了,不会继续找其他出口。 ...

2023-12-06 · 3 min · 566 words · 老墨

Python教程04:运算符

Python 教程 04:运算符 “巧妇难为无米之炊。” 有了数据类型,接下来就要学会如何操作这些数据。运算符就是操作数据的工具,就像厨房里的刀、铲、勺,每种工具各有用途。 1. 算术运算符 最基础的运算符,用于数学计算。 基本运算 运算符 说明 示例 结果 + 加法 5 + 3 8 - 减法 5 - 3 2 * 乘法 5 * 3 15 / 除法 5 / 2 2.5 // 整除 5 // 2 2 % 取模(余数) 5 % 2 1 ** 乘方 2 ** 3 8 1# 算术运算示例 2a = 10 3b = 3 4 5print(f"{a} + {b} = {a + b}") # 13 6print(f"{a} - {b} = {a - b}") # 7 7print(f"{a} * {b} = {a * b}") # 30 8print(f"{a} / {b} = {a / b}") # 3.333... 9print(f"{a} // {b} = {a // b}") # 3 10print(f"{a} % {b} = {a % b}") # 1 11print(f"{a} ** {b} = {a ** b}") # 1000 有趣的细节 除法的"历史遗留问题" ...

2023-12-04 · 5 min · 878 words · 老墨

Python教程03:数据类型基础

Python 教程 03:数据类型基础 “万物皆有类。” 在 Python 的世界里,所有数据都有自己的类型。了解数据类型,就像认识食材,知道哪些能一起烹饪,哪些会"水火不容"。 1. Python 的基础数据类型 Python 有几种基础数据类型,今天我们先学习最常用的四种: 类型 英文名 示例 说明 整数 int 42, -100, 0 没有小数点的数字 浮点数 float 3.14, -0.5, 2.0 带小数点的数字 字符串 str "Hello", 'Python' 文本数据 布尔值 bool True, False 真或假 还有一个特殊的值:None,表示"空"或"无值"。 2. 整数(int) 整数就是没有小数部分的数字,可正可负可为零。 1# 整数示例 2age = 25 3temperature = -10 4zero = 0 5 6print(age, type(age)) # 25 <class 'int'> 7print(temperature) # -10 8 9# Python 3的整数可以无限大(只要内存够) 10big_number = 1234567890123456789012345678901234567890 11print(big_number) # 正常输出,不会溢出 12 13# 不同进制的整数 14binary = 0b1010 # 二进制,等于十进制的10 15octal = 0o12 # 八进制,等于十进制的10 16hexadecimal = 0x1F # 十六进制,等于十进制的31 17print(binary, octal, hexadecimal) # 10 10 31 整数运算 1a = 10 2b = 3 3 4# 基本运算 5print(a + b) # 13 加法 6print(a - b) # 7 减法 7print(a * b) # 30 乘法 8 9# 除法:注意Python 3的除法很特别 10print(a / b) # 3.3333... 除法,结果是浮点数 11print(a // b) # 3 整除,结果是整数 12print(a % b) # 1 取模(求余数) 13 14# 乘方 15print(a ** 2) # 100 (10的2次方) 16print(2 ** 10) # 1024 这里有个有趣的现象:在 Python 3 中,10 / 3的结果是3.333...(浮点数),而不是像 Go/Java 那样得到3。如果你想要整除,必须用//。 ...

2023-11-20 · 3 min · 633 words · 老墨

Python教程02:基础语法

Python 教程 02:基础语法 “纸上得来终觉浅,绝知此事要躬行。” 学编程和学游泳一样,看再多教程也不如下水扑腾几下。今天我们来学习 Python 的基础语法,这些是写代码的"规矩"。 1. 注释:给代码写"旁白" 注释就像电影里的旁白,是写给人看的,不会被 Python 执行。写注释有两个好处: 提醒自己:三个月后回头看代码,如果没有注释,你可能会问"这是谁写的垃圾代码?"(然后发现是自己写的) 方便别人:团队协作时,注释能让其他人快速理解你的思路 单行注释 用#开头,从#开始到行尾的所有内容都是注释: 1# 这是一个单行注释 2print("Hello") # 这也是注释,可以放在代码后面 3 4# 计算圆的面积 5radius = 5 6area = 3.14 * radius ** 2 多行注释 Python 没有专门的多行注释语法,但可以用三引号('''或""")来实现: 1""" 2这是一个多行注释 3可以写很多行 4通常用于写文档字符串(docstring) 5""" 6 7''' 8单引号也可以 9但更推荐用双引号 10''' 11 12def calculate_area(radius): 13 """ 14 计算圆的面积 15 16 参数: 17 radius: 圆的半径 18 19 返回: 20 圆的面积 21 """ 22 return 3.14 * radius ** 2 最佳实践:注释要写"为什么",而不是"是什么"。比如# 计算圆的面积这种注释意义不大,因为代码本身已经很清楚了。更好的注释是:# 使用简化的π值,精确度够用且计算更快 ...

2023-11-10 · 3 min · 522 words · 老墨

Python教程01:Python简介与环境搭建

Python 教程 01:Python 简介与环境搭建 “工欲善其事,必先利其器。” 在开始学习 Python 之前,我们先要把环境搭建好。别担心,这比组装宜家家具简单多了。 1. Python 是什么? Python 是一种高级编程语言,由荷兰程序员 Guido van Rossum 于 1991 年创建。有趣的是,这个名字并非来自那条盘在树上的蟒蛇,而是源自英国喜剧团体"Monty Python"(蒙提·派森)。Guido 在开发 Python 时正在看这个喜剧团的剧集,觉得这名字"简短、独特、略带神秘",于是就用了。 不过大家还是约定俗成地用蛇做 Logo,毕竟这样看起来更酷一些。 Python 的三大特点 简单易学:语法接近自然语言,读代码就像读英文句子 功能强大:从网站开发到人工智能,从自动化脚本到科学计算,几乎无所不能 生态丰富:拥有数十万个第三方库,就像一个超级大工具箱 用一句话概括:Python 是程序员界的瑞士军刀——简单好用,功能齐全。 2. 为什么学 Python? 应用领域广泛 Web 开发:Django、Flask、FastAPI 框架让你快速搭建网站 数据分析:Pandas、NumPy、Matplotlib 是数据科学家的标配 人工智能:TensorFlow、PyTorch 支撑着深度学习的发展 自动化脚本:批量处理文件、爬虫、运维工具,让重复劳动自动化 游戏开发:Pygame 虽然小众,但也很有趣 科学计算:SciPy 在科研领域广泛应用 市场需求大 根据 TIOBE 编程语言排行榜,Python 常年稳居前三。这意味着无论你是找工作、做副业,还是只是想提升技能,Python 都是一个非常好的选择。 就像学外语,你可以学世界语(优雅但没人用),也可以学英语(实用且吃香)。Python 就是编程界的"英语"。 代码简洁优雅 Python 崇尚"用最少的代码做最多的事"。同样的功能,Python 代码往往比其他语言短 50%以上。比如打印 1 到 10: 1# Python:简洁明了 2for i in range(1, 11): 3 print(i) 非常的简洁。 3. Python 2 vs Python 3:历史的遗留问题 目前 Python 有两个主要版本: ...

2023-10-18 · 2 min · 369 words · 老墨