本周目标
- 理解继承(Inheritance) 的概念,学会如何从父类派生子类
- 掌握方法重写(Override) 和
super() 的用法 - 理解多态(Polymorphism) 的核心思想——“同一个接口,不同实现”
- 掌握常用的特殊方法(Magic Methods),如
__str__、__repr__、__add__
一、为什么需要继承?
继承的核心价值在于代码复用和扩展性:
- 代码复用子类可以自动拥有父类的所有属性和方法,无需重复编写
- 扩展性子类可以在父类的基础上增加新的属性和方法,或重写父类的方法来改变行为
- 多态的基础
在 AI 领域,继承无处不在:
- PyTorch 中,你定义的每一个神经网络模型都继承自
torch.nn.Module,然后只需重写 forward() 方法 - 数据处理中,你可以定义
BaseDataset 基类,然后派生出 ImageDataset、TextDataset 等子类 - 训练流程中,你可以定义
BaseTrainer,然后派生出 CNNTrainer、LSTMTrainer 等
二、继承的基本语法
1. 继承的定义
使用 class 子类名(父类名): 来声明继承关系:
# 父类(基类)classAnimal:def__init__(self, name, age):self.name = nameself.age = agedefeat(self):print(f"{self.name} 正在吃东西")defsleep(self):print(f"{self.name} 正在睡觉")# 子类(派生类)classDog(Animal):defbark(self):print(f"{self.name} 汪汪叫!")# 创建子类对象dog = Dog("旺财", 3)dog.eat() # 从父类继承的方法dog.sleep() # 从父类继承的方法dog.bark() # 子类自己的方法
💡 术语:父类也叫基类(Base Class) 或超类(Superclass);子类也叫派生类(Derived Class)。
2. super() —— 调用父类的方法
当子类需要执行父类的初始化逻辑时,使用 super().__init__(...) 调用父类的构造方法:
classAnimal:def__init__(self, name, age):self.name = nameself.age = agedefspeak(self):return"发出声音"classCat(Animal):def__init__(self, name, age, color):super().__init__(name, age) # 调用父类的 __init__self.color = color # 新增子类自己的属性defspeak(self):return"喵喵喵"# 重写父类方法cat = Cat("咪咪", 2, "橘色")print(cat.name) # 咪咪(来自父类)print(cat.color) # 橘色(子类新增)print(cat.speak()) # 喵喵喵(重写后)
⚠️ 重要:即使子类没有显式调用 super().__init__(),Python 也会自动调用父类的无参构造方法(如果存在)。但一旦子类定义了 __init__,就必须手动调用 super().__init__() 来初始化父类的属性,否则父类的属性不会被正确设置。
三、方法重写(Override)—— 子类定制自己的行为
子类可以对父类的方法进行重写(Override),即重新定义方法的实现:
classBird(Animal):def__init__(self, name, age, wing_span):super().__init__(name, age)self.wing_span = wing_span# 重写 speak 方法defspeak(self):return"叽叽喳喳"# 重写 eat 方法,增加额外行为defeat(self):super().eat() # 先执行父类的 eatprint(f"{self.name} 吃完后啄了啄羽毛")bird = Bird("小翠", 1, 20)print(bird.speak()) # 叽叽喳喳bird.eat()# 输出:# 小翠 正在吃东西# 小翠 吃完后啄了啄羽毛
重写时使用 super() 调用父类方法
子类重写方法时,往往希望在父类逻辑的基础上增加功能,而不是完全覆盖。这时可以用 super().方法名() 调用父类版本:
classRobot:defwork(self):print("机器人正在工作")classAIChatRobot(Robot):defwork(self):super().work() # 调用父类的工作逻辑print("并且能进行智能对话") # 增加新功能robot = AIChatRobot()robot.work()# 输出:# 机器人正在工作# 并且能进行智能对话
四、多态(Polymorphism)——“一个接口,多种形态”
1. 什么是多态?
多态是指同一个方法名,在不同的类中可以有完全不同的实现。调用者不需要关心对象的实际类型,只需要调用相同的方法名,程序会自动根据对象类型执行对应的版本。
2. 多态的经典示例
classAnimal:defspeak(self):pass# 抽象方法,由子类实现classDog(Animal):defspeak(self):return"汪汪"classCat(Animal):defspeak(self):return"喵喵"classDuck(Animal):defspeak(self):return"嘎嘎"defmake_animal_speak(animal):"""多态函数:不管传入什么动物,都调用 speak 方法"""print(f"{animal.__class__.__name__}: {animal.speak()}")# 使用多态animals = [Dog(), Cat(), Duck()]for animal in animals: make_animal_speak(animal)# 输出:# Dog: 汪汪# Cat: 喵喵# Duck: 嘎嘎
💡 多态的价值:新增一个 Pig 类,只要它实现了 speak() 方法,make_animal_speak 函数无需任何修改,就能直接支持它。这符合开闭原则(对扩展开放,对修改关闭)。
3. 多态在 AI 中的应用场景
在训练模型时,我们可能使用不同的模型架构(CNN、RNN、Transformer),但它们都有相同的接口 train()、evaluate()、predict()。训练脚本可以接受任何模型对象,调用相同的方法,实现统一的训练流程——这就是多态的力量。
classBaseModel:deftrain(self, data):raise NotImplementedErrordefpredict(self, x):raise NotImplementedErrorclassCNNModel(BaseModel):deftrain(self, data):print("CNN 训练中...")defpredict(self, x):print("CNN 预测中...")classRNNModel(BaseModel):deftrain(self, data):print("RNN 训练中...")defpredict(self, x):print("RNN 预测中...")defrun_experiment(model, data): model.train(data) model.predict(data)# 可以传入任意模型run_experiment(CNNModel(), "图片数据")run_experiment(RNNModel(), "序列数据")
五、特殊方法(Magic Methods / Dunder Methods)
Python 类中有许多以双下划线开头和结尾的方法,被称为特殊方法(Magic Methods)。它们定义了类的行为,让对象能够响应 Python 内置操作。
1. __str__ 和 __repr__ —— 对象的字符串表示
__str__:给用户看的友好字符串(通过 print() 或 str() 触发)__repr__:给开发者看的精确字符串(通过 repr() 或直接输入对象触发)
classBook:def__init__(self, title, author, price):self.title = titleself.author = authorself.price = pricedef__str__(self):returnf"《{self.title}》作者:{self.author},价格:¥{self.price}"def__repr__(self):returnf"Book('{self.title}', '{self.author}', {self.price})"book = Book("Python编程", "张三", 59)print(book) # 调用 __str__: 《Python编程》作者:张三,价格:¥59print(repr(book)) # 调用 __repr__: Book('Python编程', '张三', 59)
2. __len__ —— 让对象支持 len()
classLibrary:def__init__(self):self.books = []defadd_book(self, book):self.books.append(book)def__len__(self):returnlen(self.books)lib = Library()lib.add_book(Book("A", "a", 10))lib.add_book(Book("B", "b", 20))print(len(lib)) # 2
3. 运算符重载(如 __add__、__eq__ 等)
通过特殊方法,可以让自定义对象支持 +、== 等运算符:
classVector:def__init__(self, x, y):self.x = xself.y = ydef__add__(self, other):"""向量加法"""ifnotisinstance(other, Vector):raise TypeError("只能与 Vector 相加")return Vector(self.x + other.x, self.y + other.y)def__eq__(self, other):"""向量相等判断"""returnself.x == other.x andself.y == other.ydef__str__(self):returnf"Vector({self.x}, {self.y})"v1 = Vector(1, 2)v2 = Vector(3, 4)v3 = v1 + v2 # 调用 __add__print(v3) # Vector(4, 6)print(v1 == v2) # False
💡 常见特殊方法:
__add____sub____mul____truediv____eq____lt____getitem____setitem____call__
六、实战项目:动物继承体系 + 动物园管理系统
我们将构建一个完整的动物继承体系,展示继承、重写和多态,并实现一个简单的动物园管理程序。
类设计
Animal(抽象基类)├── __init__: name, age├── speak(): 抽象方法├── eat(): 通用实现├── __str__: 显示信息Mammal(哺乳动物) extends Animal├── __init__: name, age, fur_color├── give_birth(): 胎生Bird(鸟类) extends Animal├── __init__: name, age, wing_span├── fly(): 飞行Reptile(爬行动物) extends Animal├── __init__: name, age, is_venomous├── crawl(): 爬行Dog(狗) extends Mammal├── speak(): "汪汪"├── wag_tail(): 摇尾巴Cat(猫) extends Mammal├── speak(): "喵喵"├── purr(): 打呼噜Eagle(鹰) extends Bird├── speak(): "嘶鸣"├── hunt(): 捕猎Zoo(动物园) 管理所有动物├── add_animal()├── list_animals()├── make_all_speak()└── find_by_type()
完整代码
# ============================================# 动物继承体系 + 动物园管理系统# 知识点:继承、方法重写、多态、特殊方法# ============================================classAnimal:"""动物基类"""def__init__(self, name, age):self.name = nameself.age = agedefeat(self):print(f"{self.name} 正在进食")defspeak(self):# 抽象方法,子类必须重写raise NotImplementedError("子类必须实现 speak 方法")def__str__(self):returnf"{self.__class__.__name__}({self.name}, {self.age}岁)"def__repr__(self):returnself.__str__()classMammal(Animal):"""哺乳动物类"""def__init__(self, name, age, fur_color):super().__init__(name, age)self.fur_color = fur_colordefgive_birth(self):print(f"{self.name} 生了一只小宝宝")classBird(Animal):"""鸟类"""def__init__(self, name, age, wing_span):super().__init__(name, age)self.wing_span = wing_span # 翼展(厘米)deffly(self):print(f"{self.name} 展翅高飞,翼展 {self.wing_span} cm")classReptile(Animal):"""爬行动物类"""def__init__(self, name, age, is_venomous):super().__init__(name, age)self.is_venomous = is_venomousdefcrawl(self):print(f"{self.name} 正在爬行")# ---------- 具体动物子类 ----------classDog(Mammal):defspeak(self):return"汪汪!"defwag_tail(self):print(f"{self.name} 摇着尾巴,很开心!")classCat(Mammal):defspeak(self):return"喵喵~"defpurr(self):print(f"{self.name} 发出咕噜咕噜的声音")classEagle(Bird):defspeak(self):return"嘶鸣——"defhunt(self):print(f"{self.name} 正在捕猎")classSnake(Reptile):defspeak(self):return"嘶嘶嘶..."defeat(self):# 重写 eat 方法,增加蛇特有的进食行为super().eat()print(f"{self.name} 一口吞下了猎物!")# ---------- 动物园类 ----------classZoo:"""动物园管理类"""def__init__(self, name):self.name = nameself.animals = [] # 存放所有动物对象defadd_animal(self, animal):"""添加动物"""self.animals.append(animal)print(f"✅ {animal.name} 已加入 {self.name}")deflist_animals(self):"""列出所有动物"""ifnotself.animals:print("🏚️ 动物园暂时没有动物")returnprint(f"\n{'='*50}")print(f" 🦁 {self.name} 动物名录")print(f" 总数:{len(self.animals)} 只")print(f"{'='*50}")for i, animal inenumerate(self.animals, 1): type_name = animal.__class__.__name__print(f"{i}. {type_name} | {animal} | 叫声:{animal.speak()}")print(f"{'='*50}")defmake_all_speak(self):"""让所有动物叫一遍(多态演示)"""print(f"\n🔊 {self.name} 大合唱:")for animal inself.animals:print(f" {animal.name}:{animal.speak()}")deffind_by_type(self, class_name):"""根据类型名称查找动物""" result = []for animal inself.animals:if animal.__class__.__name__ == class_name: result.append(animal)return resultdef__len__(self):"""返回动物总数"""returnlen(self.animals)def__str__(self):returnf"🏛️ {self.name}({len(self.animals)} 只动物)"# ========== 测试和演示 ==========if __name__ == "__main__":# 创建动物园 zoo = Zoo("幸福动物园")print(f"欢迎来到 {zoo}!")# 创建各种动物 dog = Dog("旺财", 3, "金色") cat = Cat("咪咪", 2, "橘色") eagle = Eagle("小鹰", 5, 180) snake = Snake("小青", 1, True)# 添加到动物园print("\n--- 添加动物 ---") zoo.add_animal(dog) zoo.add_animal(cat) zoo.add_animal(eagle) zoo.add_animal(snake)# 展示所有动物 zoo.list_animals()# 多态演示:所有动物一起叫 zoo.make_all_speak()# 演示父类和子类方法的调用print("\n--- 行为演示 ---") dog.wag_tail() cat.purr() eagle.hunt() snake.eat() # 重写了 eat 方法# 特殊方法演示print(f"\n动物园大小:{len(zoo)} 只动物")print(zoo) # 调用 __str__# 按类型查找print("\n--- 查找哺乳动物 ---") mammals = zoo.find_by_type("Mammal")for m in mammals:print(f" {m.name}")
运行效果示例
欢迎来到 🏛️ 幸福动物园(0 只动物)!--- 添加动物 ---✅ 旺财 已加入 幸福动物园✅ 咪咪 已加入 幸福动物园✅ 小鹰 已加入 幸福动物园✅ 小青 已加入 幸福动物园================================================== 🦁 幸福动物园 动物名录 总数:4 只==================================================1. Dog | Dog(旺财, 3岁) | 叫声:汪汪!2. Cat | Cat(咪咪, 2岁) | 叫声:喵喵~3. Eagle | Eagle(小鹰, 5岁) | 叫声:嘶鸣——4. Snake | Snake(小青, 1岁) | 叫声:嘶嘶嘶...==================================================🔊 幸福动物园 大合唱: 旺财:汪汪! 咪咪:喵喵~ 小鹰:嘶鸣—— 小青:嘶嘶嘶...--- 行为演示 ---旺财 摇着尾巴,很开心!咪咪 发出咕噜咕噜的声音小鹰 正在捕猎小青 正在进食小青 一口吞下了猎物!动物园大小:4 只动物🏛️ 幸福动物园(4 只动物)--- 查找哺乳动物 --- 旺财 咪咪
本周小结
本周我们深入了面向对象的核心——继承与多态:
| |
|---|
| 继承 | 子类 class 子类(父类): 自动拥有父类的属性和方法 |
super() | |
| 方法重写 | |
| 多态 | 相同的方法名在不同的类中有不同的实现,调用者无需关心具体类型 |
| 鸭子类型 | Python 不强制继承,只要对象有相应方法就能使用 |
| 特殊方法 | __str__、__repr__、__add__ 等,让对象支持内置操作 |
继承和多态是面向对象编程的“灵魂”。🚀