面向对象
面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它使用"对象"来设计软件。Python 是一门支持面向对象的编程语言。
类与对象
什么是类和对象
类(Class) 是创建对象的蓝图,定义了对象的属性和方法。 对象(Object) 是类的实例,具有类定义的属性和方法。
# 类的比喻:类就像饼干模具,对象就是用模具做出的饼干
# 定义类
class Person:
"""人类"""
pass
# 创建对象(实例化)
person1 = Person()
person2 = Person()
print(person1) # <__main__.Person object at 0x...>
print(person2) # 不同的对象
print(type(person1)) # <class '__main__.Person'>
print(person1 is person2) # False(不同的对象)
定义类
使用 class 关键字定义类,类名通常使用帕斯卡命名法(Pascal Case)。
# 基本类定义
class Dog:
"""狗类"""
# 类属性(所有实例共享)
species = "犬科"
def __init__(self, name, age):
"""初始化方法(构造函数)"""
self.name = name # 实例属性
self.age = age
def bark(self):
"""实例方法"""
return f"{self.name} 汪汪叫!"
# 创建对象
dog1 = Dog("旺财", 3)
dog2 = Dog("来福", 5)
print(dog1.name) # 旺财
print(dog2.age) # 5
print(dog1.bark()) # 旺财 汪汪叫!
print(dog1.species) # 犬科
print(dog2.species) # 犬科(共享)
init 方法
__init__ 是构造函数,在创建对象时自动调用,用于初始化对象的属性。
class Car:
def __init__(self, brand, model, year):
"""初始化汽车对象"""
self.brand = brand
self.model = model
self.year = year
self.mileage = 0 # 默认属性
# 创建对象时自动调用 __init__
car1 = Car("丰田", "卡罗拉", 2020)
print(car1.brand) # 丰田
print(car1.mileage) # 0
car2 = Car("本田", "思域", 2021)
print(car2.model) # 思域
# 不带参数的 __init__
class Animal:
def __init__(self):
"""默认初始化"""
self.name = "未知"
self.age = 0
animal = Animal()
print(animal.name) # 未知
self 参数
self 代表对象本身,指向实例对象。
class Circle:
def __init__(self, radius):
self.radius = radius # self.radius 是实例属性
def area(self):
"""计算面积"""
return 3.14 * self.radius ** 2
def circumference(self):
"""计算周长"""
return 2 * 3.14 * self.radius
# 创建对象
circle = Circle(5)
print(circle.radius) # 5
print(circle.area()) # 78.5
# self 自动绑定到当前对象
circle1 = Circle(3)
circle2 = Circle(5)
# 同样的方法,不同的 self(不同的对象)
print(circle1.area()) # 28.26(radius=3)
print(circle2.area()) # 78.5(radius=5)
创建和访问对象
class Student:
def __init__(self, name, student_id):
self.name = name
self.student_id = student_id
self.grades = []
def add_grade(self, grade):
self.grades.append(grade)
def get_average(self):
if not self.grades:
return 0
return sum(self.grades) / len(self.grades)
# 创建对象
student = Student("张三", "S001")
# 访问属性
print(student.name) # 张三
print(student.student_id) # S001
# 调用方法
student.add_grade(85)
student.add_grade(90)
student.add_grade(78)
print(student.grades) # [85, 90, 78]
print(student.get_average()) # 84.333...
# 动态添加属性
student.email = "zhangsan@example.com"
print(student.email) # zhangsan@example.com
# 动态添加方法(不常见但可能)
def introduce(self):
return f"我是{self.name}"
student.introduce = introduce.__get__(student, Student)
print(student.introduce()) # 我是张三
属性与方法
实例属性
实例属性是对象特有的属性,每个对象有独立的副本。
class Person:
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)
# 每个对象有独立的实例属性
person1.age = 26
print(person1.age) # 26
print(person2.age) # 30(未受影响)
# 动态添加实例属性
person1.city = "New York"
print(person1.city) # New York
# print(person2.city) # 报错:person2 没有 city 属性
类属性
类属性是所有对象共享的属性。
class Dog:
# 类属性(所有实例共享)
species = "犬科"
count = 0
def __init__(self, name):
self.name = name
Dog.count += 1 # 修改类属性
dog1 = Dog("旺财")
dog2 = Dog("来福")
print(dog1.species) # 犬科
print(dog2.species) # 犬科
print(Dog.count) # 2
print(dog1.count) # 2
# 修改类属性影响所有实例
Dog.species = "哺乳动物"
print(dog1.species) # 哺乳动物
print(dog2.species) # 哺乳动物
# 注意:通过实例修改类属性会创建实例属性
dog1.species = "新物种"
print(dog1.species) # 新物种(实例属性)
print(dog2.species) # 哺乳动物(类属性)
print(Dog.species) # 哺乳动物(类属性)
实例方法
实例方法是最常用的方法,第一个参数是 self。
class Calculator:
def __init__(self, brand):
self.brand = brand
self.result = 0
def add(self, a, b):
"""加法"""
self.result = a + b
return self.result
def subtract(self, a, b):
"""减法"""
self.result = a - b
return self.result
def clear(self):
"""清空"""
self.result = 0
calc = Calculator("Casio")
print(calc.add(5, 3)) # 8
print(calc.result) # 8
calc.clear()
print(calc.result) # 0
类方法
类方法使用 @classmethod 装饰器,第一个参数是 cls,代表类本身。
class Person:
species = "人类"
def __init__(self, name):
self.name = name
@classmethod
def from_birth_year(cls, name, birth_year):
"""从出生年份创建实例"""
current_year = 2025
age = current_year - birth_year
# 返回一个新的实例
return cls(name, age)
@classmethod
def get_species(cls):
"""获取类属性"""
return cls.species
# 使用类方法创建对象
person = Person.from_birth_year("Alice", 1990)
print(person.name) # Alice
print(person.age) # 35
# 通过类调用类方法
print(Person.get_species()) # 人类
# 也可以通过实例调用
print(person.get_species()) # 人类
静态方法
静态方法使用 @staticmethod 装饰器,不需要 self 或 cls 参数。
class MathUtils:
"""数学工具类"""
@staticmethod
def add(a, b):
"""加法(不访问实例或类)"""
return a + b
@staticmethod
def multiply(a, b):
"""乘法"""
return a * b
@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
# 通过类调用静态方法
print(MathUtils.add(5, 3)) # 8
print(MathUtils.is_prime(7)) # True
# 通过实例调用(也可以但不常见)
utils = MathUtils()
print(utils.multiply(4, 5)) # 20
实例方法 vs 类方法 vs 静态方法
class Example:
class_var = "类变量"
def __init__(self, instance_var):
self.instance_var = instance_var
def instance_method(self):
"""实例方法:可以访问实例属性和类属性"""
print(f"实例变量: {self.instance_var}")
print(f"类变量: {self.class_var}")
return "实例方法"
@classmethod
def class_method(cls):
"""类方法:可以访问类属性,不能访问实例属性"""
print(f"类变量: {cls.class_var}")
# print(f"实例变量: {self.instance_var}") # 报错
return "类方法"
@staticmethod
def static_method():
"""静态方法:不能访问实例属性和类属性"""
# print(f"实例变量: {self.instance_var}") # 报错
# print(f"类变量: {cls.class_var}") # 报错
return "静态方法"
ex = Example("实例变量")
ex.instance_method() # 实例方法
Example.class_method() # 类方法
Example.static_method() # 静态方法
属性装饰器
使用 @property 将方法转换为属性访问。
class Person:
def __init__(self, name, age):
self._name = name # 使用 _ 表示受保护的属性
self._age = age
@property
def name(self):
"""获取名字(只读属性)"""
return self._name
@property
def age(self):
"""获取年龄"""
return self._age
@age.setter
def age(self, value):
"""设置年龄(带验证)"""
if value < 0:
raise ValueError("年龄不能为负数")
if value > 150:
raise ValueError("年龄不合法")
self._age = value
@age.deleter
def age(self):
"""删除年龄"""
print("删除年龄属性")
del self._age
person = Person("Alice", 25)
# 像访问属性一样访问方法
print(person.name) # Alice(调用 getter)
print(person.age) # 25
# 修改属性(调用 setter)
person.age = 26
print(person.age) # 26
# 验证
try:
person.age = -5 # ValueError: 年龄不能为负数
except ValueError as e:
print(e)
# 删除属性(调用 deleter)
del person.age
# 删除年龄属性
# name 是只读属性
# person.name = "Bob" # 报错:没有 setter
继承
继承允许一个类(子类)获得另一个类(父类)的属性和方法。
单继承
子类继承一个父类。
# 父类(基类)
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
return f"{self.name} 正在吃东西"
def sleep(self):
return f"{self.name} 正在睡觉"
# 子类(派生类)
class Dog(Animal):
def bark(self):
return f"{self.name} 汪汪叫!"
# 创建子类对象
dog = Dog("旺财")
# 子类继承父类的方法
print(dog.eat()) # 旺财 正在吃东西
print(dog.sleep()) # 旺财 正在睡觉
# 子类自己的方法
print(dog.bark()) # 旺财 汪汪叫!
# isinstance 检查
print(isinstance(dog, Dog)) # True
print(isinstance(dog, Animal)) # True
print(isinstance(dog, object)) # True(所有类继承自 object)
调用父类方法
使用 super() 调用父类方法。
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
return f"{self.name} 正在吃东西"
class Dog(Animal):
def __init__(self, name, breed):
# 调用父类的 __init__
super().__init__(name)
self.breed = breed
def eat(self):
# 调用父类的 eat 方法
parent_eat = super().eat()
return f"{parent_eat}(狗狗吃骨头)"
dog = Dog("旺财", "金毛")
print(dog.name) # 旺财
print(dog.breed) # 金毛
print(dog.eat()) # 旺财 正在吃东西(狗狗吃骨头)
方法重写
子类可以重写(覆盖)父类的方法。
class Animal:
def speak(self):
return "动物发出声音"
class Dog(Animal):
def speak(self):
return "汪汪!"
class Cat(Animal):
def speak(self):
return "喵喵!"
dog = Dog()
cat = Cat()
print(dog.speak()) # 汪汪!
print(cat.speak()) # 喵喵!
# 仍然可以访问父类方法
animal = Animal()
print(animal.speak()) # 动物发出声音
添加新属性和方法
子类可以添加父类没有的属性和方法。
class Vehicle:
def __init__(self, brand):
self.brand = brand
def start(self):
return f"{self.brand} 车辆启动"
class Car(Vehicle):
def __init__(self, brand, model, num_doors):
# 调用父类 __init__
super().__init__(brand)
self.model = model # 新增属性
self.num_doors = num_doors # 新增属性
def start(self):
# 重写父类方法
return f"{self.brand} {self.model} 启动"
def open_trunk(self):
# 新增方法
return "打开后备箱"
car = Car("丰田", "卡罗拉", 4)
print(car.brand) # 丰田(继承)
print(car.model) # 卡罗拉(新增)
print(car.start()) # 丰田 卡罗拉 启动
print(car.open_trunk()) # 打开后备箱(新增)
多继承
Python 支持多继承,一个子类可以继承多个父类。
class Father:
def __init__(self, father_name):
self.father_name = father_name
def father_method(self):
return "父亲的方法"
class Mother:
def __init__(self, mother_name):
self.mother_name = mother_name
def mother_method(self):
return "母亲的方法"
class Child(Father, Mother):
def __init__(self, name, father_name, mother_name):
self.name = name
Father.__init__(self, father_name)
Mother.__init__(self, mother_name)
def child_method(self):
return "孩子的方法"
child = Child("小明", "爸爸", "妈妈")
print(child.father_method()) # 父亲的方法
print(child.mother_method()) # 母亲的方法
print(child.child_method()) # 孩子的方法
方法解析顺序 (MRO)
多继承时,Python 使用 C3 线性化算法确定方法解析顺序。
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
d = D()
print(d.method()) # B(按照 D -> B -> C -> A 的顺序)
# 查看 MRO
print(D.__mro__)
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
# 使用 super() 按照 MRO 顺序调用
class D(B, C):
def method(self):
return f"D -> {super().method()}"
print(D().method()) # D -> B
多继承的最佳实践
# 使用 super() 和协同多继承
class LoggingMixin:
"""日志混入类"""
def log(self, message):
print(f"[LOG] {message}")
class CacheMixin:
"""缓存混入类"""
def __init__(self):
self._cache = {}
def cache_get(self, key):
return self._cache.get(key)
def cache_set(self, key, value):
self._cache[key] = value
class Database(LoggingMixin, CacheMixin):
"""数据库类(继承多个混入类)"""
def __init__(self):
super().__init__() # 初始化所有父类
self.log("数据库初始化")
def query(self, sql):
self.log(f"执行查询: {sql}")
# 查询逻辑...
return "查询结果"
db = Database()
db.query("SELECT * FROM users")
db.cache_set("key1", "value1")
print(db.cache_get("key1")) # value1
多态
多态允许不同类的对象对同一方法作出不同的响应。
方法重写实现多态
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "汪汪!"
class Cat(Animal):
def speak(self):
return "喵喵!"
class Cow(Animal):
def speak(self):
return "哞哞!"
# 多态:同样的方法调用,不同的行为
animals = [Dog(), Cat(), Cow()]
for animal in animals:
print(animal.speak())
# 输出:
# 汪汪!
# 喵喵!
# 哞哞!
鸭子类型(Duck Typing)
Python 的多态不依赖于继承,而是依赖于对象的行为。
# 鸭子类型:"如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子"
class Duck:
def speak(self):
return "嘎嘎!"
def walk(self):
return "鸭子走路"
class Person:
def speak(self):
return "你好!"
def walk(self):
return "人类走路"
def make_it_speak_and_walk(obj):
"""不关心对象的类型,只关心对象是否有相应的方法"""
print(obj.speak())
print(obj.walk())
duck = Duck()
person = Person()
make_it_speak_and_walk(duck) # 嘎嘎! 鸭子走路
make_it_speak_and_walk(person) # 你好! 人类走路
# 实际应用:len() 函数
print(len([1, 2, 3])) # 3(列表)
print(len("hello")) # 5(字符串)
print(len({"a": 1, "b": 2})) # 2(字典)
抽象基类 (ABC)
使用抽象基类定义接口规范。
from abc import ABC, abstractmethod
class Shape(ABC):
"""形状抽象基类"""
@abstractmethod
def area(self):
"""计算面积(抽象方法,子类必须实现)"""
pass
@abstractmethod
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.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radius
# 不能直接实例化抽象类
# shape = Shape() # TypeError
# 可以实例化具体子类
rectangle = Rectangle(5, 3)
circle = Circle(4)
print(rectangle.area()) # 15
print(circle.perimeter()) # 25.12
运算符重载
通过重载魔术方法实现对象的多态行为。
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 __str__(self):
"""字符串表示"""
return f"Vector({self.x}, {self.y})"
def __eq__(self, other):
"""重载 == 运算符"""
return self.x == other.x and self.y == other.y
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2 # 使用 + 运算符
print(v3) # Vector(4, 6)
print(v1 == Vector(1, 2)) # True
封装
封装是隐藏对象的实现细节,只暴露必要的接口。
公有、受保护、私有属性
Python 使用命名约定表示访问级别。
class Person:
def __init__(self, name, age, salary):
self.name = name # 公有属性
self._age = age # 受保护属性(单下划线)
self.__salary = salary # 私有属性(双下划线)
def get_salary(self):
"""访问私有属性"""
return self.__salary
def set_salary(self, salary):
"""修改私有属性"""
if salary < 0:
raise ValueError("薪水不能为负数")
self.__salary = salary
person = Person("Alice", 25, 50000)
# 公有属性:自由访问
print(person.name) # Alice
person.name = "Bob"
print(person.name) # Bob
# 受保护属性:可以访问但不建议(约定)
print(person._age) # 25(可以访问但不推荐)
person._age = 26
# 私有属性:名称修饰,不能直接访问
# print(person.__salary) # 报错:AttributeError
print(person.get_salary()) # 50000(通过方法访问)
person.set_salary(60000)
print(person.get_salary()) # 60000
# 实际上私有属性被重命名为 _Person__salary
print(person._Person__salary) # 60000(不推荐这样访问)
使用 property 封装
class BankAccount:
def __init__(self, balance):
self.__balance = balance
@property
def balance(self):
"""获取余额(只读)"""
return self.__balance
def deposit(self, amount):
"""存款"""
if amount <= 0:
raise ValueError("存款金额必须大于0")
self.__balance += amount
def withdraw(self, amount):
"""取款"""
if amount <= 0:
raise ValueError("取款金额必须大于0")
if amount > self.__balance:
raise ValueError("余额不足")
self.__balance -= amount
account = BankAccount(1000)
# 读取余额
print(account.balance) # 1000
# 修改余额(只能通过方法)
account.deposit(500)
print(account.balance) # 1500
account.withdraw(200)
print(account.balance) # 1300
# 不能直接修改余额
# account.balance = 10000 # 报错:没有 setter
封装的好处
class Temperature:
"""温度类:封装华氏度和摄氏度的转换"""
def __init__(self, celsius):
self.__celsius = celsius
@property
def celsius(self):
"""获取摄氏度"""
return self.__celsius
@celsius.setter
def celsius(self, value):
"""设置摄氏度"""
if value < -273.15:
raise ValueError("温度不能低于绝对零度")
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
temp = Temperature(25)
print(temp.celsius) # 25
print(temp.fahrenheit) # 77.0(自动计算)
# 设置华氏度
temp.fahrenheit = 100
print(temp.celsius) # 37.777...(自动转换)
魔术方法
魔术方法(Magic Methods)是以双下划线开头和结尾的特殊方法。
str 和 repr
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
"""字符串表示(用户友好)"""
return f"Person(name={self.name}, age={self.age})"
def __repr__(self):
"""开发者表示(用于调试)"""
return f"Person('{self.name}', {self.age})"
person = Person("Alice", 25)
print(person) # Person(name=Alice, age=25)(使用 __str__)
print(repr(person)) # Person('Alice', 25)(使用 __repr__)
# 在列表或字典中使用
people = [person]
print(people) # [Person('Alice', 25)](使用 __repr__)
比较魔术方法
class Money:
def __init__(self, amount, currency):
self.amount = amount
self.currency = currency
def __eq__(self, other):
"""== 运算符"""
if not isinstance(other, Money):
return False
return self.amount == other.amount and self.currency == other.currency
def __lt__(self, other):
"""< 运算符"""
if not isinstance(other, Money):
return NotImplemented
if self.currency != other.currency:
raise ValueError("不能比较不同货币")
return self.amount < other.amount
def __le__(self, other):
"""<= 运算符"""
return self == other or self < other
m1 = Money(100, "USD")
m2 = Money(100, "USD")
m3 = Money(50, "USD")
print(m1 == m2) # True
print(m1 > m3) # True
print(m1 <= m2) # True
算术运算符
class Complex:
"""复数类"""
def __init__(self, real, imag):
self.real = real
self.imag = imag
def __add__(self, other):
"""+ 运算符"""
return Complex(self.real + other.real, self.imag + other.imag)
def __sub__(self, other):
"""- 运算符"""
return Complex(self.real - other.real, self.imag - other.imag)
def __mul__(self, other):
"""* 运算符"""
real = self.real * other.real - self.imag * other.imag
imag = self.real * other.imag + self.imag * other.real
return Complex(real, imag)
def __str__(self):
return f"{self.real} + {self.imag}i"
c1 = Complex(2, 3)
c2 = Complex(1, 4)
print(c1 + c2) # 3 + 7i
print(c1 - c2) # 1 + -1i
print(c1 * c2) # -10 + 11i
容器魔术方法
class CustomList:
"""自定义列表类"""
def __init__(self, items=None):
self.__items = items if items is not None else []
def __len__(self):
"""len() 函数"""
return len(self.__items)
def __getitem__(self, index):
"""索引访问"""
return self.__items[index]
def __setitem__(self, index, value):
"""索引赋值"""
self.__items[index] = value
def __delitem__(self, index):
"""删除元素"""
del self.__items[index]
def __contains__(self, item):
"""in 运算符"""
return item in self.__items
def __iter__(self):
"""迭代"""
return iter(self.__items)
def __str__(self):
return str(self.__items)
lst = CustomList([1, 2, 3, 4, 5])
print(len(lst)) # 5
print(lst[0]) # 1
lst[0] = 10
print(lst[0]) # 10
print(3 in lst) # True
for item in lst:
print(item) # 10 2 3 4 5
可调用对象
class Counter:
def __init__(self):
self.count = 0
def __call__(self, increment=1):
"""使对象可调用"""
self.count += increment
return self.count
counter = Counter()
print(counter.count) # 0
# 像函数一样调用对象
print(counter()) # 1
print(counter(5)) # 6
print.counter) # 6
类方法与静态方法
我们之前已经介绍过,这里再补充一些内容。
使用场景对比
class Date:
"""日期类"""
def __init__(self, day, month, year):
self.day = day
self.month = month
self.year = year
# 实例方法:操作实例数据
def format_date(self):
return f"{self.year}-{self.month:02d}-{self.day:02d}"
# 类方法:创建实例的工厂方法
@classmethod
def from_string(cls, date_string):
"""从字符串创建日期"""
day, month, year = map(int, date_string.split("-"))
return cls(day, month, year)
# 静态方法:工具函数,不依赖类或实例
@staticmethod
def is_valid_date(day, month, year):
"""检查日期是否有效"""
if month < 1 or month > 12:
return False
if day < 1 or day > 31:
return False
return True
# 使用实例方法
date1 = Date(25, 12, 2025)
print(date1.format_date()) # 2025-12-25
# 使用类方法创建对象
date2 = Date.from_string("25-12-2025")
print(date2.format_date()) # 2025-12-25
# 使用静态方法
print(Date.is_valid_date(25, 12, 2025)) # True
print(Date.is_valid_date(32, 13, 2025)) # False
classmethod 的应用
class Pizza:
"""披萨类"""
def __init__(self, ingredients):
self.ingredients = ingredients
def __str__(self):
return f"Pizza({', '.join(self.ingredients)})"
@classmethod
def margherita(cls):
"""玛格丽特披萨"""
return cls(["番茄酱", "马苏里拉奶酪", "罗勒"])
@classmethod
def pepperoni(cls):
"""意式香肠披萨"""
return cls(["番茄酱", "马苏里拉奶酪", "意式香肠"])
# 使用类方法创建预设对象
pizza1 = Pizza.margherita()
pizza2 = Pizza.pepperoni()
print(pizza1) # Pizza(番茄酱, 马苏里拉奶酪, 罗勒)
print(pizza2) # Pizza(番茄酱, 马苏里拉奶酪, 意式香肠)
OOP 最佳实践
1. 使用组合优先于继承
# 不推荐:深层继承
class Animal:
pass
class Dog(Animal):
pass
class Bulldog(Dog):
pass
# 推荐:组合
class Engine:
def start(self):
return "引擎启动"
class Car:
def __init__(self):
self.engine = Engine() # 组合
def start(self):
return self.engine.start()
2. 遵循 SOLID 原则
# S - 单一职责原则
class User:
"""用户类:只负责用户数据"""
def __init__(self, name, email):
self.name = name
self.email = email
class UserRepository:
"""用户仓储:只负责数据持久化"""
def save(self, user):
pass
class EmailService:
"""邮件服务:只负责发送邮件"""
def send_welcome(self, user):
pass
# O - 开闭原则:对扩展开放,对修改关闭
class PaymentProcessor:
"""支付处理器基类"""
def process(self, amount):
raise NotImplementedError
class CreditCardProcessor(PaymentProcessor):
def process(self, amount):
return f"信用卡支付 {amount}"
class PayPalProcessor(PaymentProcessor):
def process(self, amount):
return f"PayPal支付 {amount}"
3. 使用有意义的命名
# 不推荐
class A:
def m(self, x):
return x * 2
# 推荐
class Calculator:
def multiply_by_two(self, number):
return number * 2
4. 适当使用文档字符串
class Student:
"""学生类
用于管理学生信息和成绩。
Attributes:
name: 学生姓名
student_id: 学号
grades: 成绩列表
"""
def __init__(self, name, student_id):
"""初始化学生对象
Args:
name: 学生姓名
student_id: 学号
"""
self.name = name
self.student_id = student_id
self.grades = []
5. 使用类型提示
from typing import List, Optional
class Product:
def __init__(self, name: str, price: float):
self.name: str = name
self.price: float = price
def get_discounted_price(self, discount_rate: float) -> float:
"""计算折扣后的价格"""
return self.price * (1 - discount_rate)
小结
本章节介绍了 Python 的面向对象编程:
- 类与对象: 类定义, init, self, 创建对象
- 属性与方法: 实例属性, 类属性, 实例方法, 类方法, 静态方法, property
- 继承: 单继承, 调用父类方法, 方法重写, 多继承, MRO
- 多态: 方法重写, 鸭子类型, 抽象基类, 运算符重载
- 封装: 公有/受保护/私有属性, property, 封装的好处
- 魔术方法: str, repr, 比较, 算术, 容器, 可调用
- 类方法与静态方法: 使用场景对比, classmethod 应用
掌握面向对象编程是构建大型、可维护 Python 应用的关键。下一章我们将学习文件操作,包括文件读写、路径处理等。