第一部分:面向对象编程基础概念
1.1 为什么需要面向对象编程?
传统编程 vs 面向对象编程
PYTHON
# 传统过程式编程
student1_name = "张三"
student1_age = 20
student1_score = 85
student2_name = "李四"
student2_age = 21
student2_score = 90
def calculate_grade(student_score):
if student_score >= 90:
return "A"
elif student_score >= 80:
return "B"
else:
return "C"
# 问题:数据和函数分离,难以管理
PYTHON
# 面向对象编程
class Student:
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
def calculate_grade(self):
if self.score >= 90:
return "A"
elif self.score >= 80:
return "B"
else:
return "C"
# 创建对象
student1 = Student("张三", 20, 85)
student2 = Student("李四", 21, 90)
# 统一处理
print(student1.calculate_grade()) # B
print(student2.calculate_grade()) # A
1.2 三大核心特征
1.2.1 封装(Encapsulation)
PYTHON
class BankAccount:
def __init__(self, account_number, owner, balance=0):
self._account_number = account_number # 受保护属性
self.owner = owner # 公开属性
self.__balance = balance # 私有属性(双下划线)
self.__transaction_history = [] # 私有属性
def deposit(self, amount):
"""存款"""
if amount > 0:
self.__balance += amount
self.__add_transaction(f"存款: +{amount}")
return True
return False
def withdraw(self, amount):
"""取款"""
if 0 < amount <= self.__balance:
self.__balance -= amount
self.__add_transaction(f"取款: -{amount}")
return True
return False
def get_balance(self):
"""获取余额(通过方法访问私有属性)"""
return self.__balance
def __add_transaction(self, record):
"""私有方法:添加交易记录"""
self.__transaction_history.append(record)
def get_transaction_history(self):
"""获取交易历史"""
return self.__transaction_history.copy() # 返回副本,保护数据
# 使用
account = BankAccount("123456", "张三", 1000)
account.deposit(500)
account.withdraw(200)
print(f"余额: {account.get_balance()}") # 1300
print(f"交易记录: {account.get_transaction_history()}")
# 无法直接访问私有属性
# print(account.__balance) # 错误!AttributeError
# print(account._BankAccount__balance) # 可以访问,但不推荐
1.2.2 继承(Inheritance)
PYTHON
# 父类(基类)
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print(f"{self.name}正在吃东西...")
def sleep(self):
print(f"{self.name}正在睡觉...")
def make_sound(self):
print(f"{self.name}发出声音...")
# 子类(派生类)
class Dog(Animal): # 继承Animal类
def __init__(self, name, age, breed):
super().__init__(name, age) # 调用父类初始化方法
self.breed = breed # 子类特有属性
# 方法重写(方法覆盖)
def make_sound(self):
print(f"{self.name}汪汪叫!")
# 子类特有方法
def fetch(self):
print(f"{self.name}正在捡球...")
class Cat(Animal):
def __init__(self, name, age, color):
super().__init__(name, age)
self.color = color
def make_sound(self):
print(f"{self.name}喵喵叫!")
def climb_tree(self):
print(f"{self.name}正在爬树...")
# 使用
dog = Dog("旺财", 3, "金毛")
cat = Cat("咪咪", 2, "白色")
print(f"{dog.name} 是 {dog.breed}")
dog.eat() # 继承自父类
dog.make_sound() # 重写的方法
dog.fetch() # 子类特有方法
print(f"\n{cat.name} 是 {cat.color}的")
cat.sleep() # 继承自父类
cat.make_sound() # 重写的方法
cat.climb_tree() # 子类特有方法
1.2.3 多态(Polymorphism)
PYTHON
class Shape:
def area(self):
"""计算面积(抽象方法,子类必须实现)"""
pass # 未实现
def perimeter(self):
"""计算周长"""
pass
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14159 * self.radius ** 2
def perimeter(self):
return 2 * 3.14159 * self.radius
class Triangle(Shape):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def area(self):
# 海伦公式
s = (self.a + self.b + self.c) / 2
return (s * (s - self.a) * (s - self.b) * (s - self.c)) ** 0.5
def perimeter(self):
return self.a + self.b + self.c
# 多态的使用
def print_shape_info(shape):
"""这个函数可以处理任何Shape的子类"""
print(f"面积: {shape.area():.2f}")
print(f"周长: {shape.perimeter():.2f}")
# 创建不同的形状对象
shapes = [
Rectangle(5, 10),
Circle(7),
Triangle(3, 4, 5)
]
# 多态调用
for i, shape in enumerate(shapes, 1):
print(f"\n形状{i}:")
print_shape_info(shape)
# 自动调用对应子类的方法
第二部分:Python中的继承深度解析
2.1 继承的类型
2.1.1 单继承
PYTHON
# 最基础的继承关系
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
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
def introduce(self):
base_intro = super().introduce() # 调用父类方法
return f"{base_intro},学号是{self.student_id}"
2.1.2 多继承
PYTHON
# 多重继承示例
class Flyable:
def fly(self):
return "我可以飞行"
def altitude(self):
return "我能飞到高空"
class Swimmable:
def swim(self):
return "我可以游泳"
def depth(self):
return "我能潜入深海"
class Runnable:
def run(self):
return "我可以奔跑"
def speed(self):
return "我能高速奔跑"
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
return f"{self.name}在吃东西"
# 多重继承:一个类继承自多个父类
class Duck(Animal, Flyable, Swimmable):
def __init__(self, name):
Animal.__init__(self, name) # 显式调用父类初始化
def abilities(self):
return f"{self.name}:{self.fly()},{self.swim()},还会走路"
# 多重继承:注意方法解析顺序(MRO)
class Platypus(Animal, Swimmable, Runnable):
def __init__(self, name):
super().__init__(name) # 使用super()调用
def abilities(self):
return f"{self.name}:{self.swim()},{self.run()}"
# 使用
duck = Duck("唐老鸭")
print(duck.abilities()) # 唐老鸭:我可以飞行,我可以游泳,还会走路
print(duck.eat()) # 唐老鸭在吃东西
platypus = Platypus("鸭嘴兽")
print(platypus.abilities()) # 鸭嘴兽:我可以游泳,我可以奔跑
# 查看方法解析顺序
print("Duck的MRO:", Duck.__mro__)
print("Platypus的MRO:", Platypus.__mro__)
2.2 方法解析顺序(MRO)
PYTHON
# 菱形继承问题
class A:
def method(self):
return "A的方法"
class B(A):
def method(self):
return "B的方法"
class C(A):
def method(self):
return "C的方法"
class D(B, C):
pass
# Python的C3线性化算法解决菱形继承问题
d = D()
print(d.method()) # 输出:"B的方法"
# 查看MRO(Method Resolution Order)
print(D.__mro__) # (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
# 演示MRO的实际应用
class Base:
def __init__(self):
print("Base.__init__()")
self.base_value = "base"
class Left(Base):
def __init__(self):
print("Left.__init__()")
super().__init__() # 调用Base的__init__
self.left_value = "left"
class Right(Base):
def __init__(self):
print("Right.__init__()")
super().__init__() # 调用Base的__init__
self.right_value = "right"
class Child(Left, Right):
def __init__(self):
print("Child.__init__()")
super().__init__() # 调用Left的__init__
self.child_value = "child"
# 创建Child实例
child = Child()
print("\n构造完成后的属性:")
print(f"child.base_value: {hasattr(child, 'base_value')}")
print(f"child.left_value: {child.left_value}")
print(f"child.right_value: {child.right_value}")
print(f"child.child_value: {child.child_value}")
print(f"\nChild类的MRO: {Child.__mro__}")
2.3 super()函数详解
PYTHON
class BaseClass:
def __init__(self, value):
self.base_value = value
print(f"BaseClass初始化,value={value}")
def method(self):
print("BaseClass.method()")
return "base_method"
class MiddleClass1(BaseClass):
def __init__(self, value):
print(f"MiddleClass1初始化前")
super().__init__(value * 2) # 调用BaseClass.__init__
self.middle1_value = value
print(f"MiddleClass1初始化后")
def method(self):
print("MiddleClass1.method()前")
result = super().method() # 调用BaseClass.method
print(f"MiddleClass1.method()后,父类返回: {result}")
return f"middle1 -> {result}"
class MiddleClass2(BaseClass):
def __init__(self, value):
print(f"MiddleClass2初始化前")
super().__init__(value * 3)
self.middle2_value = value
print(f"MiddleClass2初始化后")
def method(self):
print("MiddleClass2.method()前")
result = super().method()
print(f"MiddleClass2.method()后,父类返回: {result}")
return f"middle2 -> {result}"
class DerivedClass(MiddleClass1, MiddleClass2):
def __init__(self, value):
print(f"DerivedClass初始化前")
super().__init__(value) # 根据MRO调用MiddleClass1.__init__
self.derived_value = value
print(f"DerivedClass初始化后")
def method(self):
print("DerivedClass.method()前")
result = super().method() # 根据MRO调用MiddleClass1.method
print(f"DerivedClass.method()后,父类返回: {result}")
return f"derived -> {result}"
# 测试
print("创建DerivedClass实例:")
derived = DerivedClass(10)
print("\n属性值:")
print(f"derived.base_value: {derived.base_value}") # 60
print(f"derived.middle1_value: {derived.middle1_value}") # 10
print(f"derived.middle2_value: {derived.middle2_value}") # 10
print(f"derived.derived_value: {derived.derived_value}") # 10
print("\n调用method方法:")
result = derived.method()
print(f"最终结果: {result}")
print(f"\nMRO顺序: {DerivedClass.__mro__}")
第三部分:抽象类深入讲解
3.1 抽象类的概念和用途
3.1.1 为什么需要抽象类?
PYTHON
# 问题:没有抽象类的设计缺陷
class Animal:
def speak(self):
"""预期子类必须实现这个方法"""
# 如果子类忘记实现,运行时才会报错
raise NotImplementedError("子类必须实现speak方法")
class Dog(Animal):
# 忘记实现speak方法
pass
class Cat(Animal):
def speak(self):
return "喵喵"
# 测试
cat = Cat()
print(cat.speak()) # 喵喵
dog = Dog()
try:
print(dog.speak()) # 运行时才报错
except NotImplementedError as e:
print(f"错误: {e}") # 错误: 子类必须实现speak方法
3.1.2 使用抽象基类
PYTHON
from abc import ABC, abstractmethod
# 抽象类定义
class Animal(ABC): # 继承ABC表示这是抽象类
def __init__(self, name):
self.name = name
# 抽象方法:子类必须实现
@abstractmethod
def speak(self):
"""动物发出声音的方法"""
pass
@abstractmethod
def move(self):
"""动物移动的方法"""
pass
# 普通方法:抽象类可以提供实现
def sleep(self):
print(f"{self.name}正在睡觉")
# 类方法
@classmethod
def get_class_info(cls):
return f"动物类: {cls.__name__}"
# 静态方法
@staticmethod
def is_animal(obj):
return hasattr(obj, 'speak') and hasattr(obj, 'move')
# 子类必须实现所有抽象方法
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
def speak(self):
return f"{self.name}汪汪叫(品种: {self.breed})"
def move(self):
return f"{self.name}用四条腿奔跑"
class Bird(Animal):
def __init__(self, name, wingspan):
super().__init__(name)
self.wingspan = wingspan
def speak(self):
return f"{self.name}叽叽喳喳叫"
def move(self):
return f"{self.name}用翅膀飞翔,翼展{self.wingspan}厘米"
# 使用抽象类
try:
# 不能实例化抽象类
# animal = Animal("抽象动物") # TypeError
pass
except TypeError as e:
print(f"错误: {e}")
# 正确使用子类
dog = Dog("旺财", "金毛")
bird = Bird("小黄", 30)
animals = [dog, bird]
for animal in animals:
print(f"\n{animal.name}:")
print(f" 叫声: {animal.speak()}")
print(f" 移动: {animal.move()}")
animal.sleep() # 调用父类的普通方法
print(f" 类信息: {animal.get_class_info()}")
print(f"\n{dog.name}是动物吗?{Animal.is_animal(dog)}") # True
3.2 抽象属性和抽象类方法
PYTHON
from abc import ABC, abstractmethod, abstractproperty
class Vehicle(ABC):
"""交通工具抽象类"""
@abstractmethod
def __init__(self, brand, model):
pass
# 普通方法
def drive(self, distance):
"""驾驶车辆"""
self._mileage += distance
return f"驾驶了{distance}公里,总里程:{self._mileage}公里"
@property
def mileage(self):
"""获取里程(属性访问器)"""
return self._mileage
class Car(Vehicle):
"""汽车类"""
def __init__(self, brand, model, engine_type):
super().__init__(brand, model)
self.engine_type = engine_type
self._fuel_type = "汽油"
self._max_speed = 200
# 实现抽象属性
@property
def fuel_type(self):
return self._fuel_type
@property
def max_speed(self):
return self._max_speed
# 实现抽象方法
def start_engine(self):
return f"{self.brand} {self.model} ({self.engine_type}引擎)启动"
def stop_engine(self):
return f"{self.brand} {self.model}熄火"
# 子类特有方法
def honk(self):
return "汽车鸣笛:滴滴!"
class ElectricScooter(Vehicle):
"""电动滑板车类"""
def __init__(self, brand, model, battery_capacity):
super().__init__(brand, model)
self.battery_capacity = battery_capacity
self._fuel_type = "电力"
self._max_speed = 25
@property
def fuel_type(self):
return self._fuel_type
@property
def max_speed(self):
return self._max_speed
def start_engine(self):
return f"电动滑板车{self.brand} {self.model}启动,电量{self.battery_capacity}Ah"
def stop_engine(self):
return "电动滑板车已关机"
def check_battery(self):
return f"电池状态: {self.battery_capacity}Ah"
# 使用
car = Car("丰田", "卡罗拉", "1.8L自然吸气")
scooter = ElectricScooter("小米", "Pro2", "12.8")
vehicles = [car, scooter]
for vehicle in vehicles:
print(f"\n{vehicle.brand} {vehicle.model}:")
print(f" 燃料类型: {vehicle.fuel_type}")
print(f" 最高速度: {vehicle.max_speed}km/h")
print(f" 启动: {vehicle.start_engine()}")
print(f" 停止: {vehicle.stop_engine()}")
# 调用普通方法
print(f" {vehicle.drive(50)}")
print(f" 当前里程: {vehicle.mileage}公里")
# 判断类型
if isinstance(vehicle, Car):
print(f" 特殊功能: {vehicle.honk()}")
elif isinstance(vehicle, ElectricScooter):
print(f" 特殊功能: {vehicle.check_battery()}")
3.3 注册虚拟子类
PYTHON
"""
虚拟子类:允许非继承的方式将类注册为抽象基类的子类
"""
from abc import ABC, abstractmethod
class Shape(ABC):
"""形状抽象类"""
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
# 方法1:使用继承
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
# 方法2:手动注册为虚拟子类
class CustomShape:
"""自定义形状,不继承Shape但注册为虚拟子类"""
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radius
# 注册为虚拟子类
Shape.register(CustomShape)
# 方法3:使用装饰器
@Shape.register
class Triangle:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def area(self):
# 海伦公式
s = (self.a + self.b + self.c) / 2
return (s * (s - self.a) * (s - self.b) * (s - self.c)) ** 0.5
def perimeter(self):
return self.a + self.b + self.c
# 测试
shapes = [
Rectangle(5, 10), # 继承的子类
CustomShape(7), # 注册的虚拟子类
Triangle(3, 4, 5) # 装饰器注册的虚拟子类
]
print("检查类型关系:")
for i, shape in enumerate(shapes, 1):
print(f"\n形状{i}: {type(shape).__name__}")
print(f" 是Shape的子类吗?{isinstance(shape, Shape)}")
print(f" 是Shape的子类(继承检查)吗?{issubclass(type(shape), Shape)}")
print(f" 面积: {shape.area():.2f}")
print(f" 周长: {shape.perimeter():.2f}")
# 尝试实例化抽象类
try:
invalid_shape = Shape()
except TypeError as e:
print(f"\n抽象类不能实例化: {e}")
第四部分:接口与协议编程
4.1 Python中的接口概念
4.1.1 鸭子类型(Duck Typing)
PYTHON
"""
Python的"鸭子类型"理念:
"如果它走路像鸭子,叫起来像鸭子,那么它就是鸭子"
"""
class Printer:
def print(self, document):
print(f"打印文档: {document}")
class Scanner:
def scan(self, document):
return f"扫描文档: {document}"
class Fax:
def fax(self, document, number):
return f"发送文档到 {number}: {document}"
# 多功能设备
class MultiFunctionDevice:
def print(self, document):
print(f"多功能机打印: {document}")
def scan(self, document):
return f"多功能机扫描: {document}"
def fax(self, document, number):
return f"多功能机发送传真到 {number}: {document}"
def test_printer(device):
"""测试打印功能 - 只关心有没有print方法"""
if hasattr(device, 'print'):
device.print("测试文档")
return True
return False
def test_scanner(device):
"""测试扫描功能"""
if hasattr(device, 'scan'):
result = device.scan("测试文档")
print(result)
return True
return False
# 测试
devices = [Printer(), Scanner(), Fax(), MultiFunctionDevice()]
print("设备测试:")
for device in devices:
print(f"\n{type(device).__name__}:")
print(f" 打印功能: {'支持' if test_printer(device) else '不支持'}")
print(f" 扫描功能: {'支持' if test_scanner(device) else '不支持'}")
4.1.2 使用抽象基类定义接口
PYTHON
from abc import ABC, abstractmethod
# 定义接口
class Printable(ABC):
@abstractmethod
def print(self, document):
pass
class Scannable(ABC):
@abstractmethod
def scan(self, document):
pass
class Faxable(ABC):
@abstractmethod
def fax(self, document, number):
pass
# 具体的类实现接口
class OldPrinter(Printable):
def print(self, document):
print(f"老式打印机打印: {document}")
class ModernPrinter(Printable, Scannable):
def print(self, document):
print(f"现代打印机打印: {document}")
def scan(self, document):
return f"现代打印机扫描: {document}"
class OfficeMachine(Printable, Scannable, Faxable):
def print(self, document):
print(f"办公设备打印: {document}")
def scan(self, document):
return f"办公设备扫描: {document}"
def fax(self, document, number):
return f"办公设备发送传真到 {number}: {document}"
def office_workflow(machine, document, fax_number=None):
"""办公工作流 - 要求机器实现特定接口"""
print(f"\n开始处理文档: {document}")
if isinstance(machine, Printable):
machine.print(document)
else:
print("设备不支持打印")
if isinstance(machine, Scannable):
result = machine.scan(document)
print(result)
if isinstance(machine, Faxable) and fax_number:
result = machine.fax(document, fax_number)
print(result)
# 测试
print("办公工作流测试:")
office_workflow(OldPrinter(), "合同")
office_workflow(ModernPrinter(), "报告")
office_workflow(OfficeMachine(), "发票", "123-456-7890")
# 接口继承检查
print(f"\n接口继承关系:")
print(f"OldPrinter 是否实现 Printable? {isinstance(OldPrinter(), Printable)}")
print(f"ModernPrinter 是否实现 Scannable? {isinstance(ModernPrinter(), Scannable)}")
print(f"OfficeMachine 是否实现所有接口? {isinstance(OfficeMachine(), (Printable, Scannable, Faxable))}")
4.2 协议(Protocol)- Python 3.8+
PYTHON
"""
Protocol:Python 3.8+ 引入的正式协议检查
允许进行静态类型检查的接口定义
"""
# 方法1:使用typing.Protocol(Python 3.8+)
from typing import Protocol, runtime_checkable
from dataclasses import dataclass
@runtime_checkable
class Drawable(Protocol):
"""可绘制对象的协议"""
def draw(self) -> str:
...
def erase(self) -> str:
...
@runtime_checkable
class Colorable(Protocol):
"""可着色对象的协议"""
def set_color(self, color: str) -> None:
...
def get_color(self) -> str:
...
# 实现协议的类
class Circle:
def __init__(self, radius, color="黑色"):
self.radius = radius
self.color = color
def draw(self) -> str:
return f"绘制圆形,半径={self.radius},颜色={self.color}"
def erase(self) -> str:
return "擦除圆形"
def set_color(self, color: str) -> None:
self.color = color
def get_color(self) -> str:
return self.color
# 额外的方法
def area(self) -> float:
return 3.14159 * self.radius ** 2
class Square:
def __init__(self, side_length, color="黑色"):
self.side_length = side_length
self.color = color
def draw(self) -> str:
return f"绘制正方形,边长={self.side_length},颜色={self.color}"
def erase(self) -> str:
return "擦除正方形"
# 函数接受协议类型的参数
def draw_shape(shape: Drawable):
print(shape.draw())
def change_color(shape: Colorable, new_color: str):
shape.set_color(new_color)
print(f"颜色已更改为: {shape.get_color()}")
# 使用dataclass实现协议
@dataclass
class Rectangle(Drawable, Colorable):
width: float
height: float
color: str = "黑色"
def draw(self) -> str:
return f"绘制矩形,宽={self.width},高={self.height},颜色={self.color}"
def erase(self) -> str:
return "擦除矩形"
def set_color(self, color: str) -> None:
self.color = color
def get_color(self) -> str:
return self.color
# 测试
print("协议测试:")
circle = Circle(5, "红色")
square = Square(10)
rectangle = Rectangle(8, 6, "蓝色")
shapes: list[Drawable] = [circle, square, rectangle]
for i, shape in enumerate(shapes, 1):
print(f"\n形状{i}:")
draw_shape(shape)
# 检查是否实现Colorable协议
if isinstance(shape, Colorable):
change_color(shape, "绿色")
print(shape.draw())
else:
print("该形状不支持颜色设置")
# 协议继承检查
print(f"\n协议实现检查:")
print(f"Circle 实现 Drawable? {isinstance(circle, Drawable)}")
print(f"Circle 实现 Colorable? {isinstance(circle, Colorable)}")
print(f"Square 实现 Drawable? {isinstance(square, Drawable)}")
print(f"Square 实现 Colorable? {isinstance(square, Colorable)}")
print(f"Rectangle 实现 Drawable? {isinstance(rectangle, Drawable)}")
print(f"Rectangle 实现 Colorable? {isinstance(rectangle, Colorable)}")
总结
我们已经完成了Python抽象类、接口和继承的系统学习!让我们回顾一下重点:
关键概念:
- 封装:隐藏实现细节,通过公共接口访问
- 继承:代码复用和层次结构
- 多态:同一操作作用于不同对象产生不同行为
- 抽象类:不能实例化,定义接口和部分实现
- 接口:定义契约,不包含实现(Python通过协议实现)
实际应用场景:
- 框架开发:定义通用接口
- 插件系统:允许第三方扩展
- API设计:提供稳定的接口
- 代码复用:提取公共功能到基类
最佳实践:
- 优先使用组合而不是继承
- 保持继承层次浅
- 使用抽象类和接口定义契约
- 遵守SOLID原则
- 适当使用设计模式