Python面向对象与文件操作_CSDN博客
·
Python 面向对象与文件操作 —— 从类基础到图书馆实战项目
📅 学习周期:2025年5月16日 - 5月22日
🏷️ 标签:Python、面向对象、类、继承、文件操作、MySQL、实战项目
📝 本文整理自学习笔记,涵盖 Python OOP 核心知识点与图书馆管理系统实战
📑 目录
- 一、文件操作
- 二、海象运算符
- 三、类的定义与基本结构
- 四、__init__ 方法详解
- 五、self 关键字底层原理
- 六、类属性与实例属性
- 七、三种方法:实例方法、类方法、静态方法
- 八、面向对象综合实战:图书馆管理系统
- 九、进阶:Python + MySQL 图书馆系统
- 十、常见易错点总结
一、文件操作
1.1 基本文件复制
def file_copy(src, dest):
# 打开源文件
src_file = open(src, 'rb')
# 读取源文件
read_src_file = src_file.read()
# 打开目标文件
dest_file = open(dest, 'wb')
# 写入目标文件
dest_file.write(read_src_file)
# 关闭文件
src_file.close()
dest_file.close()
1.2 高效文件复制(边读边写)
对于大文件,一次性读取会导致内存溢出。解决方案是分块读取,边读边写:
def efficient_file_copy(src, dest):
src_file = open(src, 'rb')
dest_file = open(dest, 'wb')
# 边读边写,每次读取 1024 字节
while chunk := src_file.read(1024):
dest_file.write(chunk)
src_file.close()
dest_file.close()
💡 这里用到了海象运算符
:=,下面详细介绍。
二、海象运算符(Walrus Operator)
Python 3.8 引入的海象运算符 :=,可以在表达式中边算边存,还能当值使用。
普通赋值 vs 海象运算符
# 普通赋值:x = 10 → 把 10 存进 x(没有返回值)
# 海象运算:(x := 10) → 把 10 存进 x,同时返回 10
场景一:避免重复计算
# ❌ 不用海象:计算了两次 len(s)
s = 'hello python'
if len(s) > 5:
print(f'长度是 {len(s)},超过5了')
# ✅ 用海象:只计算一次
s = 'hello python'
if (n := len(s)) > 5:
print(f'长度是 {n},超过5了')
场景二:while 循环读取数据
# ❌ 不用海象:代码重复
data = input('请输入:')
while data != 'quit':
print(f'你输入了:{data}')
data = input('请输入:') # 重复写了一遍 input
# ✅ 用海象:一行搞定
while (data := input('请输入:')) != 'quit':
print(f'你输入了:{data}')
场景三:列表推导式中使用
import math
numbers = [1, 5, 12, 3, 20, 8, 15]
# ❌ 不用海象:先算再筛选,计算两次
results = [math.factorial(n) for n in numbers if math.factorial(n) > 100]
# ✅ 用海象:只算一次
results = [f for n in numbers if (f := math.factorial(n)) > 100]
三、类的定义与基本结构
class Person:
home = 'earth' # 类属性
def __init__(self, name, age): # 实例属性
self.name = name
self.age = age
def eat(self): # 实例方法
print(self.name + " eats " + str(self.age))
def drink(self):
print(self.name + " is drinking " + str(self.age))
# 创建实例对象
zs = Person("张三", 20)
zs.eat()
zs.drink()
print(zs.home) # 访问类属性
四、init 方法详解
__init__ 是 Python 类中非常重要的初始化方法:
⚠️ 在一些资料中将
__init__称为"构造函数",这种说法并不严谨。
正确理解:
- 真正创建对象的是
__new__方法 __new__创建完对象后,会将对象交给__init____init__主要完成初始化操作:给对象添加属性、给属性赋值self就是__new__创建好的对象- 如果没有显式定义
__init__,系统底层会提供一个无参的__init__
class Person:
home = 'earth'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print(self.name + " eats " + str(self.age))
zs = Person("张三", 20)
zs.eat()
print(zs.home)
五、self 关键字底层原理
class Student():
school = 'atguigu'
def __init__(self, name, age):
self.name = name
self.age = age
def study(self):
print(f'年龄是{self.age}的{self.name}在学习')
lwh = Student('lwh', 21)
print(lwh.name)
print(lwh.age)
lwh.study()
底层执行过程
一. 创建模块对象
1. Student
2. lwh
二. 创建类对象
1. school(类属性)
2. __init__
3. study
三. 创建实例对象
通过 __new__ 创建,将实例对象封装传给 __init__ 中的 self
self → 实例对象的地址
在 __init__ 中通过 self.name = name 给实例对象赋值
四. 调用实例方法
self 接收实例对象的地址
有了地址就可以访问实例对象的值
六、类属性与实例属性
6.1 访问与修改类属性
class Person:
home = 'earth'
# 通过类名访问
print(Person.home) # earth
lwh = Person()
print(lwh.home) # earth
# 通过实例名修改(注意陷阱!)
lwh.home = '地球'
print(Person.home) # earth(类属性没变!)
print(lwh.home) # 地球(创建了实例属性)
# 通过类名修改
Person.home = '地球'
print(Person.home) # 地球(类属性被修改)
⚠️ 关键区别:
- 通过类名修改 → 修改的是类属性本身
- 通过实例名修改 → 在实例属性中创建同名属性,对类属性没有影响
- 实例属性与类属性不能同名,否则会有歧义
6.2 实例属性的独立性
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
# 每个实例属性都占有不同的存储空间,互不影响
zs = Person('张三', 18)
ls = Person('李四', 20)
# 也可以在实例方法中定义实例属性
zs.eat()
print(zs.gender) # 通过方法动态添加
# 也可以通过实例名添加
ls.gender = 'male'
七、三种方法:实例方法、类方法、静态方法
7.1 实例方法
class Person:
home = 'earth'
def __init__(self, name, age):
self.name = name
self.age = age
# 实例方法:第一个参数为 self,代表实例本身
def m1(self):
print(Person.home) # 访问类属性
print(self.age) # 访问实例属性
self.m2() # 调用其他实例方法
def m2(self):
print(self.home)
lwh = Person('张三', 18)
lwh.m1()
可以通过实例对象调用,也可以通过类名.方法名(self) 调用
7.2 类方法
class Person:
home = 'earth'
@classmethod
def class_method(cls):
print(cls.home) # 可以访问类属性
print(cls.__doc__) # 可以访问文档字符串
# 使用场景:获取类成员但不想创建实例对象
Person.class_method() # 通过类调用
p1 = Person()
p1.class_method() # 通过实例调用
7.3 静态方法
class Person:
home = 'earth'
@staticmethod
def static_method():
print("static method") # 不访问类/实例属性
Person.static_method() # 通过类调用
p1 = Person()
p1.static_method() # 通过实例调用
7.4 三种方法对比
| 方法类型 | 装饰器 | 第一个参数 | 能访问什么 | 调用方式 |
|---|---|---|---|---|
| 实例方法 | 无 | self(实例) |
实例属性、类属性 | 实例名.方法() |
| 类方法 | @classmethod |
cls(类) |
类属性 | 类名.方法() 或 实例名.方法() |
| 静态方法 | @staticmethod |
无 | 不访问内部信息 | 类名.方法() 或 实例名.方法() |
八、面向对象综合实战:图书馆管理系统
8.1 Book 类(书籍)
class Book:
library_name = 'Python图书馆'
count = 0
def __init__(self, book_name, author, price, stock):
self.book_name = book_name
self.author = author
self.price = price
self.stock = stock
Book.count += 1
def __str__(self):
return f'《{self.book_name}》- 作者:{self.author}'
__repr__ = __str__ # 让列表打印也用 __str__ 格式
def __lt__(self, other):
return self.price < other.price
def sell_info(self):
return {'书名': self.book_name, '作者': self.author,
'价格': self.price, '库存': self.stock}
book1 = Book('西游记', '吴承恩', 45.0, 10)
book2 = Book('红楼梦', '曹雪芹', 55.0, 8)
book3 = Book('三国演义', '罗贯中', 50.0, 12)
print(book1) # 《西游记》- 作者:吴承恩
print(book1 < book2) # True(45 < 55)
8.2 EBook 类(电子书 - 继承)
class EBook(Book):
def __init__(self, book_name, author, price, stock, file_size):
super().__init__(book_name, author, price, stock)
self.file_size = file_size
def __str__(self):
return f'《{self.book_name}》- 作者:{self.author} [电子书, 大小: {self.file_size}MB]'
def download(self):
print(f"正在下载《{self.book_name}》,文件大小:{self.file_size}MB")
ebook1 = EBook('Python入门', '小明', 29.9, 100, 15.5)
print(ebook1) # 《Python入门》- 作者:小明 [电子书, 大小: 15.5MB]
ebook1.download()
8.3 Member 类(会员系统)
class Member:
all_members = {}
def __init__(self, name, level='普通'):
self.name = name
self.level = level
self.borrowed_books = [] # 实例属性,每个对象独有
if self.name not in Member.all_members:
Member.all_members[self.name] = self.level
def __str__(self):
level = Member.all_members.get(self.name, self.level)
return f"会员:{self.name}({level})"
def __eq__(self, other):
return self.name == other.name
def borrow(self, book):
self.borrowed_books.append(book.book_name)
print(f"{self.name} 借阅了《{book.book_name}》")
def return_book(self, book):
if book.book_name in self.borrowed_books:
self.borrowed_books.remove(book.book_name)
print(f"{self.name} 归还了《{book.book_name}》")
@classmethod
def get_all_members(cls):
return cls.all_members
@classmethod
def upgrade_all(cls):
for name, level in cls.all_members.items():
if level == '普通':
cls.all_members[name] = 'VIP'
elif level == 'VIP':
cls.all_members[name] = 'SVIP'
m1 = Member('张三')
m1.borrow(book1) # 张三 借阅了《西游记》
m1.borrow(book2) # 张三 借阅了《红楼梦》
m1.return_book(book1)
8.4 Library 类(图书馆管理)
class Library:
def __init__(self, name):
self.name = name
self.books = {}
def add_book(self, book):
if self.books.get(book.book_name) is None:
self.books[book.book_name] = book
print(f'添加成功:《{book.book_name}》')
else:
print(f'《{book.book_name}》已存在')
def remove_book(self, book_name):
if book_name in self.books:
del self.books[book_name]
print(f'已删除:《{book_name}》')
def find_book(self, book_name):
return self.books.get(book_name)
def get_expensive_books(self, price_limit):
return [b for b in self.books.values() if b.price >= price_limit]
def lend(self, member, book_name):
if book_name in self.books and self.books[book_name].stock > 0:
self.books[book_name].stock -= 1
print(f'{member.name} 借阅了《{book_name}》,剩余库存:{self.books[book_name].stock}')
else:
print(f'《{book_name}》库存不足')
def receive(self, member, book_name):
if book_name in self.books:
self.books[book_name].stock += 1
print(f'{member.name} 归还了《{book_name}》,当前库存:{self.books[book_name].stock}')
def __str__(self):
return f'{self.name},共{len(self.books)}本书'
library = Library('Python图书馆')
library.add_book(book1)
library.add_book(book2)
library.add_book(book3)
library.add_book(ebook1)
library.show_all()
九、进阶:Python + MySQL 图书馆系统
9.1 数据库表设计
CREATE DATABASE IF NOT EXISTS library_db DEFAULT CHARSET utf8mb4;
USE library_db;
-- 书籍表
CREATE TABLE IF NOT EXISTS books (
id INT PRIMARY KEY AUTO_INCREMENT,
book_name VARCHAR(50) NOT NULL UNIQUE,
author VARCHAR(50) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
stock INT NOT NULL DEFAULT 0,
is_ebook TINYINT DEFAULT 0 COMMENT '0=纸质书 1=电子书',
file_size DECIMAL(10, 2) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 会员表
CREATE TABLE IF NOT EXISTS members (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL UNIQUE,
level VARCHAR(20) DEFAULT '普通',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 借阅记录表
CREATE TABLE IF NOT EXISTS borrow_records (
id INT PRIMARY KEY AUTO_INCREMENT,
member_name VARCHAR(50) NOT NULL,
book_name VARCHAR(50) NOT NULL,
borrow_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
return_date TIMESTAMP NULL DEFAULT NULL,
status VARCHAR(20) DEFAULT '借出'
);
9.2 数据库连接工具类
import pymysql
class DB:
def __init__(self, host, port, user, password, database):
self.host = host
self.port = port
self.user = user
self.password = password
self.database = database
self.conn = None
def connect(self):
self.conn = pymysql.connect(
host=self.host, port=self.port,
user=self.user, password=self.password,
database=self.database
)
def execute(self, sql, params=None):
with self.conn.cursor() as cursor:
cursor.execute(sql, params)
self.conn.commit()
def query(self, sql, params=None):
with self.conn.cursor() as cursor:
cursor.execute(sql, params)
return cursor.fetchall()
def close(self):
if self.conn:
self.conn.close()
def __str__(self):
return f'数据库连接:{self.user}@{self.host}:{self.port}/{self.database}'
9.3 关键提醒
# ❌ 危险!SQL 注入风险
db.execute(f"SELECT * FROM books WHERE name='{book_name}'")
# ✅ 安全!参数化查询
db.execute("SELECT * FROM books WHERE book_name=%s", (book_name,))
⚠️ 借还书时注意事务:UPDATE 库存 + INSERT 记录,两步要一起成功或一起失败。
十、常见易错点总结
10.1 类和对象
| 问题 | 错误写法 | 正确写法 |
|---|---|---|
| super() 多传 self | super().__init__(self, name) |
super().__init__(name) |
| 列表打印显示地址 | 只定义 __str__ |
加 __repr__ = __str__ |
| 类属性 vs 实例属性混用 | borrowed_books = [] 放类里 |
放 __init__ 里 |
| 实例方法用 @classmethod | @classmethod def lend(cls, ...) |
def lend(self, ...) |
| 函数赋值加了括号 | Person.drink = drink() |
Person.drink = drink |
__len__ 返回字典 |
return self.books |
return len(self.books) |
10.2 方法选择速查
需要访问 self(对象数据) → 实例方法 def 方法名(self)
需要访问 cls(类的数据) → 类方法 @classmethod def 方法名(cls)
什么都不需要访问 → 静态方法 @staticmethod def 方法名()
10.3 一句话总结
super().__init__()不传 self,参数要齐全__repr__ = __str__让列表打印好看- 类属性共享,实例属性独有
- 实例方法用 self,类方法用 cls
- 函数赋值不加括号,调用才加括号
- 列表里存字符串(
book_name),不存对象 self.books.values()取所有对象__len__返回数字,不是字典- for 循环遍历完再 return,不要第一个就 return
- reduce 求平均:先求和再除
知识点覆盖总览
类和对象
├── __init__ 初始化方法
├── __str__ 面向用户的打印格式
├── __repr__ 面向开发者的打印格式
├── __lt__ 小于比较
├── __eq__ 等于比较
├── __len__ len() 函数支持
├── 类属性 所有对象共享
├── 实例属性 每个对象独有
├── 实例方法 def 方法名(self)
├── 类方法 @classmethod
├── 静态方法 @staticmethod
├── 继承 class Child(Parent)
├── 方法重写 子类覆盖父类方法
└── super() 调用父类方法
文件操作
├── open() / read() / write() / close()
├── with 语句自动关闭
└── 海象运算符 := 边读边写
数据库
├── pymysql 连接
├── 参数化查询防注入
├── CRUD 操作
└── 事务管理
本文整理于 2026年5月20日,如需交流欢迎留言讨论!
更多推荐

所有评论(0)