day-027-面向对象-下

Day 27:面向对象(下)------特殊方法与类方法

OOP 最后一篇。学会 Python 的"魔法方法"让你的类像内置类型一样好用,了解类方法和静态方法的区别。最后做一个完整的小项目。


一、特殊方法(魔术方法)------让你的类更像 Python

__ 开头结尾的方法称为特殊方法(也叫魔术方法)。定义它们能让你的类支持 len()[]+for...in 等内置操作。

__len____getitem__------支持 len() 和 \[\]

python 复制代码
class Playlist:
    """歌单类"""
    def __init__(self, name):
        self.name = name
        self.songs = []

    def add_song(self, song):
        self.songs.append(song)

    def __len__(self):
        """让 len() 可用"""
        return len(self.songs)

    def __getitem__(self, index):
        """让 [] 索引可用"""
        return self.songs[index]

    def __str__(self):
        return f"《{self.name}》共 {len(self)} 首歌"

# 使用
pl = Playlist("我的最爱")
pl.add_song("晴天")
pl.add_song("夜曲")
pl.add_song("稻香")

print(len(pl))         # 3   因为实现了 __len__
print(pl[0])           # 晴天  因为实现了 __getitem__
print(pl[1:])          # ['夜曲', '稻香']  切片也行!

for song in pl:        # 实现了 __getitem__,就能 for 循环
    print(song)

__eq____lt__ 等------支持比较运算

python 复制代码
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):
        """< 操作(实现 __lt__ 后 sorted() 也能用)"""
        return self.score < other.score

    def __repr__(self):
        return f"Student({self.name}, {self.score})"

s1 = Student("小明", 85)
s2 = Student("小红", 92)
s3 = Student("小刚", 78)

print(s1 == s2)        # False  (比较成绩)
print(s1 < s2)         # True

students = [s1, s2, s3]
students.sort()        # 按成绩排序(因为实现了 __lt__)
print(students)        # [Student(小刚, 78), Student(小明, 85), Student(小红, 92)]

__add____mul__ 等------支持运算符

python 复制代码
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 __mul__(self, scalar):
        """支持 * 标量"""
        return Vector(self.x * scalar, self.y * scalar)

    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(v1 * 3)          # Vector(3, 6)

二、类方法 @classmethod------操作类本身

python 复制代码
class Student:
    school = "海淀小学"

    def __init__(self, name, score):
        self.name = name
        self.score = score

    # 实例方法:第一个参数是 self(实例)
    def info(self):
        return f"{self.name} ({self.school})"

    # 类方法:第一个参数是 cls(类本身)
    @classmethod
    def change_school(cls, new_school):
        cls.school = new_school

    # 类方法的典型用法:替代构造器
    @classmethod
    def from_string(cls, string):
        """从字符串创建 Student,如 "小明,85" """
        name, score = string.split(",")
        return cls(name.strip(), int(score))

# 使用类方法改变类属性
Student.change_school("朝阳小学")
print(Student.school)    # 朝阳小学

# 使用类方法创建实例(工厂方法)
s = Student.from_string("小红, 92")
print(s.info())          # 小红 (朝阳小学)

三、静态方法 @staticmethod------不属于实例也不属于类

python 复制代码
class MathUtils:
    @staticmethod
    def is_even(n):
        return n % 2 == 0

    @staticmethod
    def clamp(value, min_val, max_val):
        """把 value 限制在 [min_val, max_val] 之间"""
        return max(min_val, min(value, max_val))

# 静态方法不需要 self 或 cls,直接通过类名调用
print(MathUtils.is_even(10))     # True
print(MathUtils.clamp(15, 0, 10)) # 10

三种方法对比

方法类型 装饰器 第一个参数 调用方式
实例方法 self obj.method()
类方法 @classmethod cls Class.method()obj.method()
静态方法 @staticmethod Class.method()

四、实战------学生管理系统(面向对象版)

python 复制代码
class Student:
    """学生类"""
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

    @property
    def grade(self):
        if self.score >= 90:
            return "A"
        elif self.score >= 80:
            return "B"
        elif self.score >= 60:
            return "C"
        return "D"

    def __str__(self):
        return f"{self.name}, {self.age}岁, {self.score}分 ({self.grade})"

    def __repr__(self):
        return f"Student('{self.name}', {self.age}, {self.score})"


class StudentManager:
    """管理学生集合"""
    def __init__(self):
        self.students = []

    def add(self, name, age, score):
        s = Student(name, int(age), int(score))
        self.students.append(s)
        return s

    def remove(self, name):
        self.students = [s for s in self.students if s.name != name]

    def find(self, name):
        for s in self.students:
            if s.name == name:
                return s
        return None

    def __len__(self):
        return len(self.students)

    def __iter__(self):
        """让 for s in manager 可用"""
        return iter(self.students)

    def top_students(self, n=3):
        """前 n 名"""
        return sorted(self.students, key=lambda s: s.score, reverse=True)[:n]

    @property
    def average(self):
        if not self.students:
            return 0
        return sum(s.score for s in self.students) / len(self)

    @classmethod
    def from_csv(cls, filepath):
        """从 CSV 文件创建管理器"""
        import csv
        manager = cls()
        with open(filepath, "r", encoding="utf-8") as f:
            reader = csv.DictReader(f)
            for row in reader:
                manager.add(row["姓名"], row["年龄"], row["成绩"])
        return manager


# 使用
mgr = StudentManager()
mgr.add("小明", 18, 85)
mgr.add("小红", 19, 92)
mgr.add("小刚", 18, 78)
mgr.add("小丽", 20, 95)

print(f"共 {len(mgr)} 名学生,平均分 {mgr.average:.1f}")
print("前3名:")
for s in mgr.top_students():
    print(f"  {s}")

五、今日学习总结

学习内容 掌握情况 一句话要点
__len__ / __getitem__ ✅ 重点 让对象支持 len() 和 \[\]
__eq__ / __lt__ ✅ 理解 比较与排序
__add__ / __mul__ ✅ 了解 运算符重载
@classmethod ✅ 重点 第一个参数是 cls,操作类本身
@staticmethod ✅ 理解 不需要 self/cls,就是个普通函数

今日踩坑记录

  1. __lt____gt__ 只需实现一个__lt__(小于)就足够 sorted() 用了。Python 会自动推导 __gt__(大于)。
  2. 特殊方法要返回新对象还是修改自身__add__ 应该返回新对象(不修改自身),__iadd__(+=)才修改自身。
  3. 类方法用错了场景:如果不需要用到类属性或创建实例,普通函数就够了,别硬塞进类里。

六、明天学什么?

OOP 三连结束。明天开始综合练习------把前27天学的全部东西用起来,做一个完整的命令行项目。


特殊方法让你的类融入 Python 生态,类方法让类本身也能做事情。OOP 的工具箱到此齐了。
第27天,打卡完成。明天见!


本系列是个人学习笔记,如有错误欢迎在评论区指正交流。

相关推荐
华研前沿标杆游学1 小时前
2026年标杆游学机构选择指南:从资质审核到效果验收全流程本指南
python
誰能久伴不乏1 小时前
C++11 随机数生成——告别 rand()
开发语言·c++
海清河晏1111 小时前
数据结构 | 二叉平衡搜索树
开发语言·数据结构·visual studio
kuonyuma1 小时前
java之动态代理
java·开发语言
衔烛之龙11 小时前
Windows x64 构建 liboqs-java教程
java·windows·python
KouFiee1 小时前
同名隐藏基础
开发语言·c++
z落落1 小时前
C# Task WaitAll、WaitAny、WhenAll、WhenAny
开发语言·c#
兰令水1 小时前
hot100【acm版】【2026.7.11/12打卡-java版本】
java·开发语言·数据结构·算法·职场和发展
从零开始的代码生活_2 小时前
C++ string 详解:常用接口、字符串算法与深拷贝实现
开发语言·c++·后端·学习·算法