1. Python面向对象编程实战指南
作为一名有多年Python开发经验的工程师,我深知面向对象编程(OOP)在实际项目中的重要性。本文将带你深入理解Python OOP的核心概念,并通过大量实战案例展示如何将这些知识应用到真实开发场景中。
1.1 为什么需要面向对象编程
面向对象编程不仅仅是一种编程范式,更是一种思维方式。在中小型项目中,面向过程的编程方式可能足够应付,但当项目规模扩大、团队协作增多时,OOP的优势就会凸显:
- 代码复用性:通过继承和多态,可以避免重复造轮子
- 封装性:隐藏内部实现细节,只暴露必要的接口
- 可维护性:代码结构更清晰,便于长期维护和扩展
- 团队协作:清晰的类定义和接口规范,便于多人协作开发
在自动化测试框架开发中,OOP更是必不可少。一个典型的测试框架通常包含测试用例基类、测试套件管理、报告生成等多个组件,这些都需要良好的面向对象设计。
2. 异常处理的艺术
2.1 异常处理基础
异常处理是编写健壮代码的第一道防线。Python中的异常处理机制非常完善,但很多开发者并没有充分利用它的全部功能。
2.1.1 基本语法结构
python复制try:
# 可能引发异常的代码
result = 10 / 0
except ZeroDivisionError as e:
# 处理特定异常
print(f"捕获到除零错误: {e}")
except Exception as e:
# 处理其他异常
print(f"捕获到未知异常: {e}")
else:
# 没有异常时执行
print("一切正常")
finally:
# 无论是否异常都会执行
print("清理工作")
关键点:
- 尽量捕获特定异常而非笼统的Exception
- else块适合放置依赖try块成功执行的代码
- finally块常用于资源清理,如关闭文件、数据库连接等
2.1.2 异常处理的最佳实践
在实际项目中,我总结了以下异常处理经验:
- 不要吞掉异常:捕获异常后至少要记录日志
- 异常信息要具体:包含足够上下文信息便于排查
- 适当重新抛出异常:低层代码捕获处理不了的异常应该重新抛出
- 自定义异常类:为特定业务场景定义专属异常
python复制class DatabaseConnectionError(Exception):
"""自定义数据库连接异常"""
def __init__(self, host, port, message):
self.host = host
self.port = port
self.message = message
super().__init__(f"无法连接到 {host}:{port} - {message}")
def connect_database(host, port):
try:
# 模拟连接失败
raise ConnectionError("Connection refused")
except ConnectionError as e:
raise DatabaseConnectionError(host, port, str(e))
2.2 异常处理实战场景
2.2.1 文件操作异常处理
文件操作是异常的高发区,特别是当程序需要处理外部文件时。
python复制def read_file_safely(filename):
"""安全读取文件内容"""
try:
with open(filename, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
print(f"警告: 文件 {filename} 不存在")
return None
except PermissionError:
print(f"错误: 没有权限读取文件 {filename}")
return None
except UnicodeDecodeError:
print(f"错误: 文件 {filename} 编码不兼容")
return None
经验分享:
- 使用with语句自动管理文件资源
- 处理特定异常而非笼统捕获
- 给用户友好的错误提示而非原始异常信息
2.2.2 API请求异常处理
网络请求面临更多不确定性,完善的异常处理尤为重要。
python复制import requests
from requests.exceptions import RequestException
def fetch_api_data(url, timeout=10, retries=3):
"""带重试机制的API请求"""
last_exception = None
for attempt in range(retries):
try:
response = requests.get(url, timeout=timeout)
response.raise_for_status() # 检查HTTP状态码
return response.json()
except RequestException as e:
last_exception = e
print(f"请求失败 (尝试 {attempt + 1}/{retries}): {e}")
if attempt < retries - 1:
time.sleep(2 ** attempt) # 指数退避
raise last_exception or Exception("未知错误")
关键技巧:
- 实现重试机制提高可靠性
- 使用指数退避避免加重服务器负担
- 最终抛出最后一个异常保持调用栈
3. 类与对象深度解析
3.1 类的基本结构
一个完整的Python类通常包含以下部分:
python复制class MyClass:
"""类的文档字符串"""
class_attribute = "类属性" # 类属性
def __init__(self, param):
"""初始化方法"""
self.instance_attribute = param # 实例属性
def instance_method(self):
"""实例方法"""
return self.instance_attribute
@classmethod
def class_method(cls):
"""类方法"""
return cls.class_attribute
@staticmethod
def static_method():
"""静态方法"""
return "静态方法"
3.2 self的深入理解
self参数是Python类设计中最重要的概念之一,但也是最容易被误解的。
常见误区:
- self是Python关键字?错,它只是约定俗成的名称
- 每个方法都必须有self参数?只有实例方法需要
- self代表类本身?错,它代表类的实例
self的本质:
- 是实例方法的第一个参数
- Python自动将实例作为第一个参数传入
- 通过self可以访问实例属性和其他实例方法
python复制class Counter:
def __init__(self):
self.count = 0
def increment(self, amount=1):
"""增加计数器"""
self.count += amount
self._check_limit()
def _check_limit(self):
"""内部方法检查上限"""
if self.count > 100:
print("警告: 计数器超过100")
3.3 魔术方法实战
魔术方法是Python面向对象编程的强大特性,让我们自定义类的行为。
3.3.1 常用魔术方法
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 __str__(self):
"""定义打印格式"""
return f"Vector({self.x}, {self.y})"
def __len__(self):
"""定义长度行为"""
return int((self.x**2 + self.y**2)**0.5)
def __getitem__(self, index):
"""支持索引访问"""
return [self.x, self.y][index]
def __eq__(self, other):
"""定义相等比较"""
return self.x == other.x and self.y == other.y
3.3.2 上下文管理器协议
通过__enter__和__exit__实现资源自动管理。
python复制class DatabaseConnection:
def __init__(self, connection_string):
self.connection_string = connection_string
self.connection = None
def __enter__(self):
"""进入上下文时调用"""
print("建立数据库连接")
self.connection = "模拟连接对象"
return self
def execute_query(self, sql):
"""执行查询"""
if not self.connection:
raise RuntimeError("未建立连接")
print(f"执行: {sql}")
return "模拟结果"
def __exit__(self, exc_type, exc_val, exc_tb):
"""退出上下文时调用"""
print("关闭数据库连接")
self.connection = None
if exc_type:
print(f"发生异常: {exc_val}")
return True # 抑制异常
# 使用示例
with DatabaseConnection("db://user:pass@localhost") as db:
result = db.execute_query("SELECT * FROM users")
4. 类与实例属性详解
4.1 类属性 vs 实例属性
类属性:
- 定义在类内部,方法外部
- 所有实例共享
- 通过类或实例访问
- 适合存储类级别的常量或共享状态
实例属性:
- 定义在
__init__或其他方法中 - 每个实例独有
- 只能通过实例访问
- 适合存储对象特有的数据
python复制class Employee:
company = "ACME Corp" # 类属性
def __init__(self, name, salary):
self.name = name # 实例属性
self.salary = salary # 实例属性
def promote(self, raise_amount):
"""涨薪"""
self.salary += raise_amount
# 使用示例
emp1 = Employee("Alice", 50000)
emp2 = Employee("Bob", 60000)
print(emp1.company) # ACME Corp
print(emp2.company) # ACME Corp
Employee.company = "New ACME" # 修改类属性
print(emp1.company) # New ACME
print(emp2.company) # New ACME
4.2 属性访问控制
Python没有真正的私有属性,但通过命名约定实现访问控制。
python复制class BankAccount:
def __init__(self, account_holder, initial_balance):
self.account_holder = account_holder # 公开属性
self._balance = initial_balance # 保护属性(约定)
self.__pin = "1234" # 私有属性(名称改写)
def get_balance(self):
"""获取余额"""
return self._balance
def __verify_pin(self, pin):
"""私有方法"""
return self.__pin == pin
def withdraw(self, amount, pin):
"""取款"""
if not self.__verify_pin(pin):
raise ValueError("PIN码错误")
if amount > self._balance:
raise ValueError("余额不足")
self._balance -= amount
return self._balance
# 使用示例
account = BankAccount("张三", 1000)
print(account.account_holder) # 张三
print(account.get_balance()) # 1000
# print(account.__pin) # 报错
# print(account._BankAccount__pin) # 可以访问但不推荐
最佳实践:
- 公开属性:不以下划线开头,表示可以安全访问
- 保护属性:单下划线开头,表示不建议外部访问
- 私有属性:双下划线开头,Python会名称改写
- 提供getter/setter方法控制属性访问
5. 方法类型全解析
5.1 实例方法
实例方法是最常用的方法类型,第一个参数是self,用于访问实例属性和其他方法。
python复制class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
"""计算面积"""
return self.width * self.height
def resize(self, factor):
"""调整大小"""
self.width *= factor
self.height *= factor
return self # 支持链式调用
# 使用示例
rect = Rectangle(10, 20)
print(rect.area()) # 200
rect.resize(2).resize(0.5) # 链式调用
5.2 类方法
类方法使用@classmethod装饰器,第一个参数是cls,用于操作类属性或创建工厂方法。
python复制class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def from_string(cls, date_string):
"""工厂方法: 从字符串创建Date对象"""
year, month, day = map(int, date_string.split('-'))
return cls(year, month, day) # 等价于Date(year, month, day)
@classmethod
def today(cls):
"""工厂方法: 创建今天的Date对象"""
import datetime
now = datetime.datetime.now()
return cls(now.year, now.month, now.day)
# 使用示例
date1 = Date.from_string("2023-11-15")
date2 = Date.today()
5.3 静态方法
静态方法使用@staticmethod装饰器,没有自动传入的参数,相当于普通函数。
python复制class MathUtils:
@staticmethod
def add(a, b):
"""加法"""
return a + b
@staticmethod
def average(numbers):
"""计算平均值"""
return sum(numbers) / len(numbers) if numbers else 0
# 使用示例
print(MathUtils.add(5, 3)) # 8
print(MathUtils.average([1, 2, 3, 4])) # 2.5
方法选择指南:
- 需要访问实例属性 → 实例方法
- 需要操作类属性或创建工厂方法 → 类方法
- 与类相关但不需要访问类或实例状态 → 静态方法
6. 继承与多态实战
6.1 继承基础
继承是OOP的三大特性之一,Python支持单继承和多继承。
python复制class Animal:
def __init__(self, name):
self.name = name
def speak(self):
"""动物发声"""
raise NotImplementedError("子类必须实现此方法")
def move(self):
"""动物移动"""
print(f"{self.name} 在移动")
class Dog(Animal):
def speak(self):
"""狗叫"""
print(f"{self.name} 汪汪叫")
def fetch(self, item):
"""狗接东西"""
print(f"{self.name} 捡回了 {item}")
class Cat(Animal):
def speak(self):
"""猫叫"""
print(f"{self.name} 喵喵叫")
def climb(self, height):
"""猫爬高"""
print(f"{self.name} 爬上了 {height}米高的树")
# 使用示例
animals = [Dog("旺财"), Cat("咪咪")]
for animal in animals:
animal.speak() # 多态行为
6.2 super()的妙用
super()函数用于调用父类的方法,在多重继承中尤为重要。
python复制class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
print(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):
super().introduce() # 调用父类方法
print(f"我的学号是{self.student_id}")
# 使用示例
student = Student("张三", 20, "2023001")
student.introduce()
6.3 多重继承与MRO
Python支持多重继承,方法解析顺序(MRO)决定了方法查找路径。
python复制class A:
def method(self):
print("A的方法")
class B(A):
def method(self):
print("B的方法")
super().method()
class C(A):
def method(self):
print("C的方法")
super().method()
class D(B, C):
def method(self):
print("D的方法")
super().method()
# 使用方法
d = D()
d.method()
print(D.__mro__) # 查看方法解析顺序
输出结果:
code复制D的方法
B的方法
C的方法
A的方法
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
多重继承建议:
- 避免过度使用多重继承
- 使用"混入类"(Mixin)实现代码复用
- 理解MRO机制避免意外行为
7. 反射机制深入
7.1 反射基础
反射允许程序在运行时检查和修改对象的结构和行为。
python复制class Config:
def __init__(self):
self.host = "localhost"
self.port = 8080
# 反射操作示例
config = Config()
# 检查属性
print(hasattr(config, "host")) # True
print(hasattr(config, "timeout")) # False
# 获取属性
print(getattr(config, "port")) # 8080
print(getattr(config, "timeout", 30)) # 默认值30
# 设置属性
setattr(config, "timeout", 60)
print(config.timeout) # 60
# 删除属性
delattr(config, "timeout")
print(hasattr(config, "timeout")) # False
7.2 动态导入与调用
反射常用于实现插件系统或动态加载模块。
python复制import importlib
def load_plugin(plugin_name, method_name, *args, **kwargs):
"""动态加载并调用插件方法"""
try:
module = importlib.import_module(f"plugins.{plugin_name}")
if hasattr(module, method_name):
method = getattr(module, method_name)
return method(*args, **kwargs)
raise AttributeError(f"插件 {plugin_name} 没有方法 {method_name}")
except ImportError:
raise ImportError(f"无法加载插件 {plugin_name}")
# 使用示例
try:
result = load_plugin("csv_export", "export_data", data=[1, 2, 3])
print(result)
except Exception as e:
print(f"插件执行失败: {e}")
8. 路径处理最佳实践
8.1 os.path模块详解
Python的os.path模块提供了跨平台的路径操作方法。
python复制import os
# 获取当前脚本所在目录
current_dir = os.path.dirname(os.path.abspath(__file__))
print(f"当前目录: {current_dir}")
# 路径拼接
config_path = os.path.join(current_dir, "config", "settings.ini")
print(f"配置文件路径: {config_path}")
# 路径分解
dirname, basename = os.path.split(config_path)
print(f"目录部分: {dirname}")
print(f"文件名部分: {basename}")
# 获取文件扩展名
filename, ext = os.path.splitext(basename)
print(f"文件名: {filename}")
print(f"扩展名: {ext}")
# 检查路径存在
print(f"路径存在: {os.path.exists(config_path)}")
print(f"是文件: {os.path.isfile(config_path)}")
print(f"是目录: {os.path.isdir(current_dir)}")
8.2 pathlib现代路径处理
Python 3.4+引入了更面向对象的pathlib模块。
python复制from pathlib import Path
# 创建Path对象
current_path = Path(__file__).parent
config_path = current_path / "config" / "settings.ini"
# 路径操作
print(f"父目录: {config_path.parent}")
print(f"文件名: {config_path.name}")
print(f"后缀: {config_path.suffix}")
# 文件操作
if not config_path.parent.exists():
config_path.parent.mkdir(parents=True) # 创建目录
# 写入文件
config_path.write_text("[settings]\nkey=value", encoding="utf-8")
# 读取文件
content = config_path.read_text(encoding="utf-8")
print(content)
路径处理建议:
- 新项目优先使用pathlib
- 使用/运算符拼接路径
- 处理路径时考虑跨平台兼容性
- 检查路径存在性后再操作
9. 综合实战:测试框架设计
9.1 测试用例基类
python复制import time
from abc import ABC, abstractmethod
class TestCase(ABC):
"""测试用例抽象基类"""
def __init__(self, name):
self.name = name
self.start_time = None
self.end_time = None
self.duration = None
self.status = "not_run" # not_run, passed, failed, error
self.error_message = None
def setup(self):
"""测试前置条件"""
pass
def teardown(self):
"""测试后置条件"""
pass
@abstractmethod
def execute(self):
"""执行测试逻辑"""
pass
def run(self):
"""运行测试用例"""
self.start_time = time.time()
try:
self.setup()
self.execute()
self.status = "passed"
except AssertionError as e:
self.status = "failed"
self.error_message = str(e)
except Exception as e:
self.status = "error"
self.error_message = str(e)
finally:
self.teardown()
self.end_time = time.time()
self.duration = self.end_time - self.start_time
def __str__(self):
status_icons = {
"passed": "✓",
"failed": "✗",
"error": "!",
"not_run": "?"
}
icon = status_icons.get(self.status, "?")
return f"{icon} {self.name} ({self.duration:.2f}s)"
9.2 测试套件实现
python复制class TestSuite:
"""测试套件"""
def __init__(self, name="Default Test Suite"):
self.name = name
self.test_cases = []
self.results = {
"total": 0,
"passed": 0,
"failed": 0,
"error": 0,
"duration": 0
}
def add_test(self, test_case):
"""添加测试用例"""
self.test_cases.append(test_case)
def run_all(self):
"""运行所有测试用例"""
print(f"\n{'='*60}")
print(f"Running Test Suite: {self.name}")
print(f"{'='*60}")
self.results = {
"total": len(self.test_cases),
"passed": 0,
"failed": 0,
"error": 0,
"duration": 0
}
start_time = time.time()
for test_case in self.test_cases:
test_case.run()
print(test_case)
if test_case.status == "passed":
self.results["passed"] += 1
elif test_case.status == "failed":
self.results["failed"] += 1
else:
self.results["error"] += 1
self.results["duration"] = time.time() - start_time
print(f"\nTest Results:")
print(f"Total: {self.results['total']}")
print(f"Passed: {self.results['passed']}")
print(f"Failed: {self.results['failed']}")
print(f"Error: {self.results['error']}")
print(f"Duration: {self.results['duration']:.2f}s")
return self.results
9.3 具体测试用例实现
python复制class LoginTest(TestCase):
"""登录功能测试"""
def setup(self):
"""测试前置条件"""
self.username = "test_user"
self.password = "secure_password"
self.api_url = "https://api.example.com/login"
def execute(self):
"""执行测试逻辑"""
# 模拟API请求
response = {
"status": "success",
"token": "abc123"
}
# 断言测试
assert response["status"] == "success", "登录失败"
assert len(response["token"]) > 0, "未返回有效token"
print("登录测试通过")
def teardown(self):
"""测试后置条件"""
self.username = None
self.password = None
class DatabaseTest(TestCase):
"""数据库连接测试"""
def execute(self):
"""执行测试逻辑"""
# 模拟数据库连接
connection = "模拟连接对象"
assert connection is not None, "数据库连接失败"
# 模拟查询
result = [{"id": 1, "name": "测试数据"}]
assert len(result) > 0, "查询结果为空"
print("数据库测试通过")
9.4 使用测试框架
python复制if __name__ == "__main__":
# 创建测试套件
suite = TestSuite("用户功能测试")
# 添加测试用例
suite.add_test(LoginTest("登录功能测试"))
suite.add_test(DatabaseTest("数据库连接测试"))
# 运行测试
results = suite.run_all()
# 根据结果决定退出码
if results["failed"] > 0 or results["error"] > 0:
exit(1) # 测试失败
exit(0) # 测试通过
10. 高级主题与性能优化
10.1 描述符协议
描述符是Python高级特性,用于自定义属性访问。
python复制class PositiveNumber:
"""正数描述符"""
def __set_name__(self, owner, name):
self.name = name
def __get__(self, obj, objtype=None):
return obj.__dict__.get(self.name, 0)
def __set__(self, obj, value):
if not isinstance(value, (int, float)) or value <= 0:
raise ValueError("必须是正数")
obj.__dict__[self.name] = value
class Order:
quantity = PositiveNumber() # 描述符实例
price = PositiveNumber() # 描述符实例
def __init__(self, quantity, price):
self.quantity = quantity
self.price = price
def total(self):
return self.quantity * self.price
# 使用示例
try:
order = Order(5, 10.5)
print(f"总价: {order.total()}") # 52.5
order.quantity = -3 # 触发ValueError
except ValueError as e:
print(f"错误: {e}")
10.2 元类编程
元类是类的类,用于控制类的创建行为。
python复制class SingletonMeta(type):
"""单例元类"""
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class DatabaseConnection(metaclass=SingletonMeta):
"""单例数据库连接"""
def __init__(self):
print("创建新的数据库连接")
self.connection = "模拟连接对象"
def query(self, sql):
"""执行查询"""
print(f"执行: {sql}")
return "模拟结果"
# 使用示例
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(f"是同一个实例: {db1 is db2}") # True
10.3 性能优化技巧
- 使用__slots__减少内存占用
python复制class Point:
__slots__ = ['x', 'y'] # 固定属性列表
def __init__(self, x, y):
self.x = x
self.y = y
# 相比普通类,使用__slots__可以显著减少内存占用
# 但会失去动态添加属性的能力
- 避免不必要的属性访问
python复制# 不推荐
for i in range(len(self.items)):
print(self.items[i])
# 推荐
items = self.items
for i in range(len(items)):
print(items[i])
- 使用内置函数和数据结构
python复制# 不推荐
result = []
for item in items:
result.append(item * 2)
# 推荐
result = [item * 2 for item in items]
- 适当使用生成器
python复制def large_dataset_processing(data):
"""处理大数据集"""
for record in data:
# 复杂处理逻辑
processed = f"处理后的{record}"
yield processed # 生成器节省内存
# 使用示例
for result in large_dataset_processing(huge_data):
print(result)
11. 常见问题与解决方案
11.1 类设计问题
问题1:何时使用类变量 vs 实例变量?
解决方案:
- 类变量:所有实例共享的数据,如配置、常量
- 实例变量:每个实例特有的数据,如对象状态
问题2:如何设计良好的类继承层次?
建议:
- 遵循"是一个"原则(子类 is-a 父类)
- 避免过深的继承层次(通常不超过3层)
- 考虑使用组合而非继承
11.2 多继承陷阱
问题:菱形继承问题
python复制class A:
def method(self):
print("A")
class B(A):
def method(self):
print("B")
super().method()
class C(A):
def method(self):
print("C")
super().method()
class D(B, C):
def method(self):
print("D")
super().method()
d = D()
d.method()
输出:
code复制D
B
C
A
解决方案:
- 理解MRO(方法解析顺序)
- 使用super()保持调用链
- 考虑使用Mixin代替多重继承
11.3 性能问题
问题:大量小对象导致内存占用高
解决方案:
- 使用__slots__
- 考虑使用namedtuple或dataclass
- 评估是否真的需要这么多对象
python复制from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
z: float = 0.0 # 默认值
# 自动生成__init__、__repr__等方法
p = Point(1.0, 2.0)
print(p) # Point(x=1.0, y=2.0, z=0.0)
11.4 调试技巧
问题:如何调试复杂的类交互?
技巧:
- 使用print或logging输出关键状态
- 使用pdb设置断点
- 检查
__dict__查看对象属性 - 使用
inspect模块检查类结构
python复制import inspect
class MyClass:
pass
print(inspect.getmembers(MyClass)) # 查看类成员
12. 项目结构建议
良好的项目结构有助于维护面向对象代码:
code复制my_project/
├── src/ # 源代码目录
│ ├── models/ # 数据模型类
│ │ ├── user.py # 用户类
│ │ └── product.py # 产品类
│ ├── services/ # 服务类
│ │ ├── auth.py # 认证服务
│ │ └── database.py # 数据库服务
│ ├── utils/ # 工具类
│ │ ├── logger.py # 日志工具
│ │ └── validator.py # 验证工具
│ └── main.py # 程序入口
├── tests/ # 测试代码
│ ├── unit/ # 单元测试
│ └── integration/ # 集成测试
├── docs/ # 文档
└── requirements.txt # 依赖列表
关键原则:
- 每个文件一个主要类
- 相关功能组织在同一模块
- 测试与源码结构对应
- 使用绝对导入避免混乱
13. 代码质量保证
13.1 单元测试
使用unittest或pytest测试类和方法:
python复制import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual("foo".upper(), "FOO")
def test_isupper(self):
self.assertTrue("FOO".isupper())
self.assertFalse("Foo".isupper())
if __name__ == "__main__":
unittest.main()
13.2 类型提示
Python 3.5+支持类型提示,提高代码可读性:
python复制from typing import List, Dict, Optional
class User:
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
def get_friends(self) -> List["User"]:
"""获取好友列表"""
return []
def to_dict(self) -> Dict[str, object]:
"""转换为字典"""
return {"name": self.name, "age": self.age}
def find_user(user_id: int) -> Optional[User]:
"""根据ID查找用户"""
return User("Alice", 25) if user_id == 1 else None
13.3 代码规范
遵循PEP 8风格指南:
- 类名使用大驼峰:MyClass
- 方法名使用小写下划线:my_method
- 常量全大写:MAX_SIZE
- 每行不超过79字符
- 使用4空格缩进
使用工具检查:
bash复制# 安装检查工具
pip install pylint flake8 mypy
# 运行检查
pylint my_module.py
flake8 my_module.py
mypy my_module.py
14. 持续学习资源
-
官方文档:
- Python官方文档:https://docs.python.org/3/
- PEP 8风格指南:https://peps.python.org/pep-0008/
-
进阶书籍:
- 《流畅的Python》
- 《Python Cookbook》
- 《Effective Python》
-
开源项目:
- Django:https://github.com/django/django
- Requests:https://github.com/psf/requests
- Flask:https://github.com/pallets/flask
-
在线课程:
- Real Python:https://realpython.com/
- Python官方教程:https://docs.python.org/3/tutorial/
-
社区:
- Stack Overflow:https://stackoverflow.com/
- Python官方论坛:https://discuss.python.org/
- Reddit Python社区:https://www.reddit.com/r/Python/
在实际项目中应用面向对象编程时,最重要的是理解业务需求,设计合理的类结构。不要为了面向对象而面向对象,简单的需求用简单的解决方案。随着项目复杂度增加,再逐步引入更高级的面向对象特性。