跳到主要内容

面向对象

面向对象编程(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 装饰器,不需要 selfcls 参数。

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)是以双下划线开头和结尾的特殊方法。

strrepr

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 应用的关键。下一章我们将学习文件操作,包括文件读写、路径处理等。