Python 面向对象编程基础

本文档系统讲解 Python 面向对象编程(OOP)的核心知识,从零基础入门到实际应用。


一、面向对象基础概念

1.1 什么是面向对象编程

面向对象编程(Object-Oriented Programming,OOP) 是一种编程范式,它将数据和操作数据的方法封装在一起,形成"对象"。

核心思想

  • 类(Class):对象的蓝图/模板,定义了对象的属性和方法
  • 对象(Object):类的实例,是具体存在的实体
  • 封装(Encapsulation):将数据和方法包装在一起
  • 继承(Inheritance):子类继承父类的特性
  • 多态(Polymorphism):同一操作作用于不同对象产生不同结果

1.2 类与对象的关系

类(Class)          对象(Object)
  ↓                    ↓
设计图纸    →      具体的房子
模具        →      生产的产品
模板        →      实际的实例

类比理解

  • 就像汽车的"设计图纸",定义了汽车应该有什么(属性:颜色、品牌)和能做什么(方法:启动、刹车)
  • 对象 就是根据图纸造出来的"具体汽车",比如"一辆红色的宝马"

1.3 为什么要用面向对象

优点 说明
代码复用 通过继承减少重复代码
易于维护 模块化设计,修改一处不影响全局
可扩展性 新增功能只需添加新类
贴近现实 用对象模拟现实世界的事物

二、定义类与创建对象

2.1 基本语法

使用 class 关键字定义类:

class 类名:
    """类的文档字符串"""
    
    # 类属性(所有对象共享)
    类属性 =# 构造方法
    def __init__(self, 参数):
        # 实例属性(每个对象独立)
        self.属性名 = 参数
    
    # 实例方法
    def 方法名(self, 参数):
        # 方法体
        pass

2.2 第一个类

class Dog:
    """狗狗类"""
    
    # 类属性:所有狗共享
    species = "Canis familiaris"
    
    def __init__(self, name, age):
        """构造方法:创建对象时自动调用"""
        self.name = name  # 实例属性
        self.age = age    # 实例属性
    
    def bark(self):
        """狗叫方法"""
        return f"{self.name} says: 汪汪!"
    
    def introduce(self):
        """自我介绍"""
        return f"我是{self.name},今年{self.age}岁"

# 创建对象(实例化)
dog1 = Dog("旺财", 3)
dog2 = Dog("来福", 2)

# 访问属性和方法
print(dog1.name)           # 旺财
print(dog1.bark())         # 旺财 says: 汪汪!
print(dog1.introduce())    # 我是旺财,今年3岁

print(dog2.name)           # 来福
print(dog2.bark())         # 来福 says: 汪汪!

2.3 self 是什么

self 代表当前对象本身,是实例方法的第一个参数(必须写,但调用时不用传)。

class Person:
    def __init__(self, name):
        self.name = name  # self.name 表示对象的 name 属性
    
    def say_hello(self):
        # self 让方法知道是哪个对象在调用它
        print(f"你好,我是{self.name}")

p = Person("张三")
p.say_hello()  # 等价于 Person.say_hello(p)

理解 self

  • self 就是对象自己
  • 通过 self.属性 访问对象的属性
  • 通过 self.方法() 调用对象的其他方法

三、属性详解

3.1 类属性 vs 实例属性

特性 类属性 实例属性
定义位置 类内部,方法外部 __init__ 中,用 self. 定义
归属 属于类,所有对象共享 属于对象,每个对象独立
访问方式 类名.属性对象.属性 对象.属性
修改影响 影响所有对象 只影响当前对象
class Student:
    # 类属性:所有学生共享
    school = "北京大学"
    student_count = 0
    
    def __init__(self, name):
        # 实例属性:每个学生独立
        self.name = name
        self.score = 0
        Student.student_count += 1  # 修改类属性

# 创建学生
s1 = Student("张三")
s2 = Student("李四")

# 访问类属性
print(Student.school)      # 北京大学
print(s1.school)           # 北京大学
print(s2.school)           # 北京大学
print(Student.student_count)  # 2

# 访问实例属性
print(s1.name)             # 张三
print(s2.name)             # 李四

# 修改类属性
Student.school = "清华大学"
print(s1.school)           # 清华大学(所有对象都变了)

# 修改实例属性
s1.score = 90
print(s1.score)            # 90
print(s2.score)            # 0(s2 没变)

3.2 动态添加属性

Python 是动态语言,可以给对象动态添加属性:

class Cat:
    def __init__(self, name):
        self.name = name

cat = Cat("咪咪")

# 动态添加属性
cat.color = "白色"
cat.age = 2

print(cat.color)  # 白色
print(cat.age)    # 2

注意:动态添加的属性只属于当前对象,不影响其他对象。


四、方法详解

4.1 实例方法

实例方法是最常见的方法,第一个参数必须是 self,只能通过对象调用。

class Calculator:
    def __init__(self):
        self.result = 0
    
    def add(self, num):
        """实例方法"""
        self.result += num
        return self.result
    
    def subtract(self, num):
        """实例方法"""
        self.result -= num
        return self.result
    
    def reset(self):
        """重置"""
        self.result = 0

calc = Calculator()
print(calc.add(5))       # 5
print(calc.add(3))       # 8
print(calc.subtract(2))  # 6

4.2 类方法

类方法使用 @classmethod 装饰器,第一个参数是 cls(代表类本身),可以通过类或对象调用。

class DateUtil:
    """日期工具类"""
    
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day
    
    @classmethod
    def from_string(cls, date_string):
        """类方法:从字符串创建对象"""
        year, month, day = map(int, date_string.split('-'))
        return cls(year, month, day)
    
    @classmethod
    def today(cls):
        """类方法:获取今天的日期对象"""
        import datetime
        now = datetime.datetime.now()
        return cls(now.year, now.month, now.day)
    
    def show(self):
        return f"{self.year}-{self.month:02d}-{self.day:02d}"

# 使用类方法创建对象
date1 = DateUtil.from_string("2024-05-20")
print(date1.show())  # 2024-05-20

date2 = DateUtil.today()
print(date2.show())  # 2024-XX-XX(当前日期)

4.3 静态方法

静态方法使用 @staticmethod 装饰器,不需要 selfcls 参数,与类和对象无关,只是逻辑上属于这个类。

class MathUtil:
    """数学工具类"""
    
    @staticmethod
    def is_prime(n):
        """静态方法:判断是否为素数"""
        if n < 2:
            return False
        for i in range(2, int(n**0.5) + 1):
            if n % i == 0:
                return False
        return True
    
    @staticmethod
    def factorial(n):
        """静态方法:计算阶乘"""
        if n <= 1:
            return 1
        return n * MathUtil.factorial(n - 1)

# 直接通过类调用(不需要创建对象)
print(MathUtil.is_prime(17))    # True
print(MathUtil.is_prime(18))    # False
print(MathUtil.factorial(5))    # 120

# 也可以通过对象调用(不推荐)
util = MathUtil()
print(util.is_prime(7))         # True

4.4 三种方法对比

方法类型 装饰器 第一个参数 调用方式 用途
实例方法 self 对象.方法() 操作对象数据
类方法 @classmethod cls 类.方法() 或 对象.方法() 操作类数据、创建对象
静态方法 @staticmethod 类.方法() 或 对象.方法() 独立功能、工具函数

五、构造函数与析构函数

5.1 构造函数 init

构造函数在创建对象时自动调用,用于初始化对象的属性。

class Book:
    def __init__(self, title, author, price):
        """构造函数"""
        self.title = title
        self.author = author
        self.price = price
        self.is_borrowed = False  # 默认未借出
        print(f"《{title}》已入库")
    
    def info(self):
        return f"《{self.title}》作者:{self.author},价格:¥{self.price}"

# 创建对象时自动调用 __init__
book1 = Book("Python编程", "张三", 59.9)
book2 = Book("数据结构", "李四", 49.9)

print(book1.info())
print(book2.info())

5.2 带默认参数的构造函数

class User:
    def __init__(self, username, password, is_vip=False, level=1):
        self.username = username
        self.password = password
        self.is_vip = is_vip
        self.level = level
    
    def show(self):
        vip_status = "VIP" if self.is_vip else "普通用户"
        return f"{self.username} - {vip_status} - 等级{self.level}"

# 使用默认参数
user1 = User("alice", "123456")
print(user1.show())  # alice - 普通用户 - 等级1

# 覆盖默认参数
user2 = User("bob", "abc123", is_vip=True, level=5)
print(user2.show())  # bob - VIP - 等级5

5.3 析构函数 del

析构函数在对象被销毁时自动调用,用于清理资源。

class FileHandler:
    def __init__(self, filename):
        self.filename = filename
        self.file = open(filename, 'w')
        print(f"打开文件:{filename}")
    
    def write(self, content):
        self.file.write(content)
    
    def __del__(self):
        """析构函数:对象销毁时自动调用"""
        self.file.close()
        print(f"关闭文件:{self.filename}")

# 使用
handler = FileHandler("test.txt")
handler.write("Hello, World!")

# 当 handler 不再被引用时,__del__ 自动调用
del handler  # 手动删除对象

注意:Python 有垃圾回收机制,通常不需要手动管理内存,__del__ 主要用于释放外部资源(如文件、网络连接等)。


六、继承

6.1 什么是继承

继承允许一个类(子类)继承另一个类(父类)的属性和方法,实现代码复用。

# 父类(基类)
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def eat(self):
        return f"{self.name}正在吃东西"
    
    def sleep(self):
        return f"{self.name}正在睡觉"

# 子类(派生类)
class Dog(Animal):
    def bark(self):
        return f"{self.name}:汪汪!"

class Cat(Animal):
    def meow(self):
        return f"{self.name}:喵喵!"

# 使用
dog = Dog("旺财", 3)
cat = Cat("咪咪", 2)

# 继承父类的方法
print(dog.eat())    # 旺财正在吃东西
print(cat.sleep())  # 咪咪正在睡觉

# 子类自己的方法
print(dog.bark())   # 旺财:汪汪!
print(cat.meow())   # 咪咪:喵喵!

6.2 方法重写(Override)

子类可以重写父类的方法,提供自己的实现。

class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        return "动物发出声音"

class Dog(Animal):
    def speak(self):
        # 重写父类方法
        return f"{self.name}:汪汪!"

class Cat(Animal):
    def speak(self):
        # 重写父类方法
        return f"{self.name}:喵喵!"

# 使用
animals = [Dog("旺财"), Cat("咪咪"), Animal("动物")]
for animal in animals:
    print(animal.speak())

# 输出:
# 旺财:汪汪!
# 咪咪:喵喵!
# 动物发出声音

6.3 super() 调用父类

使用 super() 可以在子类中调用父类的方法。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print("Person.__init__ 被调用")
    
    def introduce(self):
        return f"我叫{self.name},今年{self.age}岁"

class Student(Person):
    def __init__(self, name, age, student_id):
        # 调用父类的构造函数
        super().__init__(name, age)
        self.student_id = student_id
        print("Student.__init__ 被调用")
    
    def introduce(self):
        # 调用父类的方法并扩展
        base = super().introduce()
        return f"{base},学号:{self.student_id}"

s = Student("张三", 20, "2024001")
print(s.introduce())
# 输出:
# Person.__init__ 被调用
# Student.__init__ 被调用
# 我叫张三,今年20岁,学号:2024001

6.4 多重继承

Python 支持一个类继承多个父类。

class Flyable:
    """可飞行"""
    def fly(self):
        return "我能飞!"

class Swimmable:
    """可游泳"""
    def swim(self):
        return "我能游泳!"

class Duck(Flyable, Swimmable):
    """鸭子:既能飞又能游泳"""
    def quack(self):
        return "嘎嘎!"

duck = Duck()
print(duck.fly())    # 我能飞!
print(duck.swim())   # 我能游泳!
print(duck.quack())  # 嘎嘎!

方法解析顺序(MRO)

print(Duck.__mro__)
# (<class 'Duck'>, <class 'Flyable'>, <class 'Swimmable'>, <class 'object'>)

七、多态

7.1 什么是多态

多态(Polymorphism) 是指同一操作作用于不同对象产生不同的结果。

class Animal:
    def speak(self):
        raise NotImplementedError("子类必须实现此方法")

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

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

class Cow(Animal):
    def speak(self):
        return "哞哞!"

# 多态:同一个函数,不同对象产生不同结果
def animal_sound(animal):
    print(animal.speak())

# 使用
dog = Dog()
cat = Cat()
cow = Cow()

animal_sound(dog)  # 汪汪!
animal_sound(cat)  # 喵喵!
animal_sound(cow)  # 哞哞!

7.2 鸭子类型

Python 是动态语言,不强制要求类型继承,只要对象有相应的方法就可以使用。

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

class Car:
    def speak(self):
        return "嘀嘀!"

class Person:
    def speak(self):
        return "你好!"

# 只要对象有 speak 方法,就可以调用
def make_sound(obj):
    if hasattr(obj, 'speak'):
        print(obj.speak())
    else:
        print("这个对象不会发声")

make_sound(Dog())    # 汪汪!
make_sound(Car())    # 嘀嘀!
make_sound(Person()) # 你好!

八、封装与访问控制

8.1 公有与私有

Python 通过命名约定实现访问控制:

类型 命名规则 访问权限
公有 name 任何地方都可以访问
保护 _name 约定:类内部和子类可以访问
私有 __name 只能在类内部访问(名称改写)
class BankAccount:
    def __init__(self, owner, balance):
        self.owner = owner          # 公有属性
        self._account_type = "储蓄"  # 保护属性
        self.__balance = balance    # 私有属性(外部无法直接访问)
    
    # 公有方法
    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return f"存入 ¥{amount},当前余额:¥{self.__balance}"
        return "存入金额必须大于0"
    
    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            return f"取出 ¥{amount},当前余额:¥{self.__balance}"
        return "余额不足或金额无效"
    
    def get_balance(self):
        """获取余额(getter)"""
        return self.__balance

# 使用
account = BankAccount("张三", 1000)

# 访问公有属性
print(account.owner)          # 张三

# 访问保护属性(可以访问,但不推荐)
print(account._account_type)  # 储蓄

# 访问私有属性(会报错)
# print(account.__balance)    # AttributeError

# 通过方法访问私有属性
print(account.get_balance())  # 1000
print(account.deposit(500))   # 存入 ¥500,当前余额:¥1500
print(account.withdraw(200))  # 取出 ¥200,当前余额:¥1300

8.2 名称改写机制

Python 对私有属性进行名称改写(Name Mangling):

class MyClass:
    def __init__(self):
        self.__private = "私有属性"

obj = MyClass()

# 直接访问会报错
# print(obj.__private)  # AttributeError

# 实际上可以通过改写后的名称访问(不推荐)
print(obj._MyClass__private)  # 私有属性

九、属性装饰器

9.1 @property 装饰器

使用 @property 可以将方法变成属性一样访问。

class Circle:
    def __init__(self, radius):
        self._radius = radius
    
    @property
    def radius(self):
        """获取半径(getter)"""
        return self._radius
    
    @radius.setter
    def radius(self, value):
        """设置半径(setter)"""
        if value < 0:
            raise ValueError("半径不能为负数")
        self._radius = value
    
    @property
    def area(self):
        """计算面积(只读属性)"""
        return 3.14159 * self._radius ** 2
    
    @property
    def circumference(self):
        """计算周长(只读属性)"""
        return 2 * 3.14159 * self._radius

# 使用
c = Circle(5)

# 像访问属性一样调用方法
print(c.radius)         # 5
print(c.area)           # 78.53975
print(c.circumference)  # 31.4159

# 设置属性(自动调用 setter)
c.radius = 10
print(c.area)           # 314.159

# 设置无效值会报错
# c.radius = -5         # ValueError: 半径不能为负数

# 只读属性不能设置
# c.area = 100          # AttributeError: can't set attribute

9.2 完整示例:温度转换

class Temperature:
    def __init__(self, celsius=0):
        self._celsius = celsius
    
    @property
    def celsius(self):
        """摄氏度"""
        return self._celsius
    
    @celsius.setter
    def celsius(self, value):
        self._celsius = value
    
    @property
    def fahrenheit(self):
        """华氏度(只读)"""
        return self._celsius * 9/5 + 32
    
    @fahrenheit.setter
    def fahrenheit(self, value):
        """设置华氏度,自动转换为摄氏度"""
        self._celsius = (value - 32) * 5/9
    
    @property
    def kelvin(self):
        """开尔文(只读)"""
        return self._celsius + 273.15

# 使用
temp = Temperature(25)
print(f"摄氏度:{temp.celsius}°C")       # 25°C
print(f"华氏度:{temp.fahrenheit}°F")   # 77.0°F
print(f"开尔文:{temp.kelvin}K")        # 298.15K

# 设置华氏度
temp.fahrenheit = 100
print(f"摄氏度:{temp.celsius}°C")       # 37.777...°C

十、魔术方法(特殊方法)

10.1 什么是魔术方法

魔术方法是以双下划线开头和结尾的特殊方法,用于实现对象的特定行为。

10.2 字符串表示方法

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __str__(self):
        """用户友好的字符串表示(print 调用)"""
        return f"Person(name='{self.name}', age={self.age})"
    
    def __repr__(self):
        """开发者的字符串表示(交互式环境调用)"""
        return f"Person('{self.name}', {self.age})"

p = Person("张三", 25)
print(str(p))   # Person(name='张三', age=25)
print(repr(p))  # Person('张三', 25)

10.3 比较方法

class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score
    
    def __eq__(self, other):
        """等于 =="""
        return self.score == other.score
    
    def __lt__(self, other):
        """小于 <"""
        return self.score < other.score
    
    def __le__(self, other):
        """小于等于 <="""
        return self.score <= other.score
    
    def __gt__(self, other):
        """大于 >"""
        return self.score > other.score
    
    def __ge__(self, other):
        """大于等于 >="""
        return self.score >= other.score
    
    def __str__(self):
        return f"{self.name}: {self.score}"

# 使用
s1 = Student("张三", 85)
s2 = Student("李四", 90)
s3 = Student("王五", 85)

print(s1 < s2)   # True
print(s1 == s3)  # True
print(s2 > s1)   # True

# 排序
students = [s1, s2, s3]
students.sort()
for s in students:
    print(s)
# 张三: 85
# 王五: 85
# 李四: 90

10.4 算术运算符

class Vector:
    """二维向量"""
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __add__(self, other):
        """加法 +"""
        return Vector(self.x + other.x, self.y + other.y)
    
    def __sub__(self, other):
        """减法 -"""
        return Vector(self.x - other.x, self.y - other.y)
    
    def __mul__(self, scalar):
        """乘法 *(数乘)"""
        return Vector(self.x * scalar, self.y * scalar)
    
    def __str__(self):
        return f"Vector({self.x}, {self.y})"
    
    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

# 使用
v1 = Vector(1, 2)
v2 = Vector(3, 4)

print(v1 + v2)      # Vector(4, 6)
print(v2 - v1)      # Vector(2, 2)
print(v1 * 3)       # Vector(3, 6)

10.5 容器类方法

class MyList:
    """自定义列表"""
    def __init__(self):
        self._data = []
    
    def __len__(self):
        """长度 len()"""
        return len(self._data)
    
    def __getitem__(self, index):
        """获取元素 []"""
        return self._data[index]
    
    def __setitem__(self, index, value):
        """设置元素 [] = """
        self._data[index] = value
    
    def __contains__(self, item):
        """包含 in"""
        return item in self._data
    
    def append(self, item):
        self._data.append(item)
    
    def __iter__(self):
        """迭代"""
        return iter(self._data)

# 使用
my_list = MyList()
my_list.append(1)
my_list.append(2)
my_list.append(3)

print(len(my_list))      # 3
print(my_list[0])        # 1
my_list[0] = 100
print(my_list[0])        # 100
print(2 in my_list)      # True

for item in my_list:
    print(item)

10.6 常用魔术方法速查

方法 用途 示例
__init__ 构造函数 obj = Class()
__del__ 析构函数 del obj
__str__ 字符串表示 str(obj), print(obj)
__repr__ 开发者字符串 repr(obj)
__eq__ 等于 obj1 == obj2
__lt__ 小于 obj1 < obj2
__add__ 加法 obj1 + obj2
__sub__ 减法 obj1 - obj2
__len__ 长度 len(obj)
__getitem__ 索引访问 obj[key]
__setitem__ 索引赋值 obj[key] = value
__contains__ 包含 item in obj
__iter__ 迭代 for item in obj
__call__ 对象调用 obj()

十一、面向对象设计原则

11.1 单一职责原则(SRP)

一个类应该只有一个引起它变化的原因。

# ❌ 不好的设计:一个类做太多事
class UserManager:
    def create_user(self): pass
    def delete_user(self): pass
    def send_email(self): pass      # 不应该在这里
    def generate_report(self): pass  # 不应该在这里

# ✅ 好的设计:职责分离
class UserService:
    def create_user(self): pass
    def delete_user(self): pass

class EmailService:
    def send_email(self): pass

class ReportService:
    def generate_report(self): pass

11.2 开闭原则(OCP)

对扩展开放,对修改关闭。

# ❌ 不好的设计:每次新增形状都要修改
class AreaCalculator:
    def calculate(self, shape):
        if shape.type == "circle":
            return 3.14 * shape.radius ** 2
        elif shape.type == "rectangle":
            return shape.width * shape.height

# ✅ 好的设计:通过继承扩展
class Shape:
    def area(self):
        raise NotImplementedError

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height

# 新增形状不需要修改现有代码
class Triangle(Shape):
    def area(self):
        return 0.5 * self.base * self.height

11.3 里氏替换原则(LSP)

子类应该能够替换父类而不影响程序正确性。

class Bird:
    def fly(self):
        return "I can fly!"

# ❌ 不好的设计:企鹅不能飞
class Penguin(Bird):
    def fly(self):
        raise Exception("Penguins can't fly!")

# ✅ 好的设计:合理划分继承层次
class Bird:
    def move(self):
        return "I can move!"

class FlyingBird(Bird):
    def fly(self):
        return "I can fly!"

class Penguin(Bird):
    def swim(self):
        return "I can swim!"

11.4 依赖倒置原则(DIP)

高层模块不应该依赖低层模块,两者都应该依赖抽象。

from abc import ABC, abstractmethod

# 抽象接口
class Database(ABC):
    @abstractmethod
    def save(self, data): pass

# 具体实现
class MySQLDatabase(Database):
    def save(self, data):
        print(f"Saving to MySQL: {data}")

class MongoDBDatabase(Database):
    def save(self, data):
        print(f"Saving to MongoDB: {data}")

# 高层模块依赖抽象,不依赖具体实现
class UserService:
    def __init__(self, database: Database):
        self.db = database
    
    def save_user(self, user):
        self.db.save(user)

# 可以轻松切换数据库
service1 = UserService(MySQLDatabase())
service2 = UserService(MongoDBDatabase())

十二、综合示例

12.1 图书管理系统

from datetime import datetime, timedelta

class Book:
    """图书类"""
    def __init__(self, isbn, title, author, total_copies=1):
        self.isbn = isbn
        self.title = title
        self.author = author
        self.total_copies = total_copies
        self.available_copies = total_copies
    
    def __str__(self):
        return f"《{self.title}》作者:{self.author}"
    
    def is_available(self):
        return self.available_copies > 0
    
    def borrow(self):
        if self.is_available():
            self.available_copies -= 1
            return True
        return False
    
    def return_book(self):
        if self.available_copies < self.total_copies:
            self.available_copies += 1
            return True
        return False

class Member:
    """会员类"""
    def __init__(self, member_id, name):
        self.member_id = member_id
        self.name = name
        self.borrowed_books = []
        self.max_books = 3
    
    def can_borrow(self):
        return len(self.borrowed_books) < self.max_books
    
    def borrow_book(self, book):
        if not self.can_borrow():
            return False, "已达到最大借书数量"
        if not book.is_available():
            return False, "该书暂无库存"
        
        book.borrow()
        due_date = datetime.now() + timedelta(days=30)
        self.borrowed_books.append({
            'book': book,
            'borrow_date': datetime.now(),
            'due_date': due_date
        })
        return True, f"借阅成功,请于 {due_date.strftime('%Y-%m-%d')} 前归还"
    
    def return_book(self, book):
        for record in self.borrowed_books:
            if record['book'] == book:
                book.return_book()
                self.borrowed_books.remove(record)
                return True, "归还成功"
        return False, "您没有借阅此书"

class Library:
    """图书馆类"""
    def __init__(self, name):
        self.name = name
        self.books = {}
        self.members = {}
    
    def add_book(self, book):
        self.books[book.isbn] = book
        print(f"入库:{book}")
    
    def register_member(self, member):
        self.members[member.member_id] = member
        print(f"注册会员:{member.name}")
    
    def find_book(self, isbn):
        return self.books.get(isbn)
    
    def find_member(self, member_id):
        return self.members.get(member_id)
    
    def list_available_books(self):
        available = [book for book in self.books.values() if book.is_available()]
        print(f"\n可借阅图书(共{len(available)}本):")
        for book in available:
            print(f"  {book}(库存:{book.available_copies})")

# 使用示例
library = Library("市立图书馆")

# 添加图书
library.add_book(Book("978-7-111-1", "Python编程", "张三", 3))
library.add_book(Book("978-7-111-2", "数据结构", "李四", 2))
library.add_book(Book("978-7-111-3", "算法导论", "王五", 1))

# 注册会员
library.register_member(Member("M001", "小明"))
library.register_member(Member("M002", "小红"))

# 查看可借阅图书
library.list_available_books()

# 借书
member = library.find_member("M001")
book = library.find_book("978-7-111-1")
success, message = member.borrow_book(book)
print(f"\n{member.name} 借书:{message}")

# 再次查看
library.list_available_books()

十三、速查表

类定义速查

class MyClass:
    # 类属性
    class_attr = "共享"
    
    def __init__(self, param):
        # 实例属性
        self.instance_attr = param
    
    # 实例方法
    def instance_method(self):
        return self.instance_attr
    
    @classmethod
    def class_method(cls):
        return cls.class_attr
    
    @staticmethod
    def static_method():
        return "独立功能"
    
    @property
    def prop(self):
        return self._value
    
    @prop.setter
    def prop(self, value):
        self._value = value

继承速查

# 单继承
class Child(Parent):
    def __init__(self, param):
        super().__init__(param)

# 多继承
class Child(Parent1, Parent2):
    pass

# 方法重写
class Child(Parent):
    def method(self):
        # 调用父类方法
        result = super().method()
        # 添加自己的逻辑
        return result

访问控制速查

类型 命名 访问方式
公有 name obj.name
保护 _name obj._name(约定)
私有 __name obj._Class__name(改写后)

魔术方法速查

类别 方法 说明
构造 __init__ 构造函数
析构 __del__ 析构函数
字符串 __str__ 用户友好字符串
字符串 __repr__ 开发者字符串
比较 __eq__, __lt__ 等于、小于
算术 __add__, __sub__ 加减法
容器 __len__, __getitem__ 长度、索引
迭代 __iter__, __next__ 迭代器
调用 __call__ 对象可调用

更多推荐