二、优秀代码的核心特征
2.1 命名艺术
命名是编程中最难的事情之一(有句名言:计算机科学中只有两件难事:缓存失效和命名)。好的命名让代码自文档化。
命名原则:
名副其实:名字要准确表达意图
避免误导:不要用容易混淆的名字
有意义的区分:Product 和 ProductInfo 没有区别
读得出来:方便讨论和搜索
可搜索性:避免魔法数字和单字母变量
# ❌ 糟糕的命名
def d(x, y):
t = 0
for i in x:
t += i * y
return t
# ✅ 优秀的命名
def calculate_total_price(item_prices: List[Decimal], tax_rate: Decimal) -> Decimal:
"""
计算含税总价
"""
subtotal = sum(item_prices)
tax = subtotal * tax_rate
return subtotal + tax
# 更多命名示例
class BadNames:
def proc(self, d1, d2):
self.a = d1
self.b = d2
self.f = True
class GoodNames:
def process_payment(self, order_amount: Decimal, user_balance: Decimal) -> PaymentResult:
self.order_amount = order_amount
self.user_balance = user_balance
self.payment_successful = True
# 魔法数字 vs 命名常量
# ❌ 糟糕
if user.age > 18:
grant_access()
# ✅ 优秀
LEGAL_AGE_THRESHOLD = 18
if user.age >= LEGAL_AGE_THRESHOLD:
grant_access()
# 布尔变量命名
# ❌ 糟糕
is_not_valid = True
no_error = False
# ✅ 优秀
is_valid = True
has_error = False
can_edit = True
should_retry = False
2.2 函数设计
函数是代码组织的基本单元。好的函数应该短小、专注、只做一件事。
函数设计原则:
短小:函数应该只做一件事,并且把这件事做好
参数少:理想情况下0-2个参数,3个参数需要仔细考虑,超过3个应该封装成对象
无副作用:函数要么修改对象状态,要么返回计算结果,不要两者都做
单一抽象层次:函数内不要混合高层和低层抽象
# ❌ 糟糕的函数设计
def process_user_data(user_data):
# 验证 - 高层抽象
if not user_data.get('email'):
raise ValueError("Email required")
if '@' not in user_data['email']:
raise ValueError("Invalid email")
# 数据库操作 - 低层抽象
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
cursor.execute("SELECT * FROM users WHERE email = ?", (user_data['email'],))
existing = cursor.fetchone()
# 业务逻辑 - 中层抽象
if existing:
return "User already exists"
# 密码哈希 - 低层抽象
hashed = hashlib.sha256(user_data['password'].encode()).hexdigest()
# 更多数据库操作
cursor.execute("INSERT INTO users (email, password_hash) VALUES (?, ?)",
(user_data['email'], hashed))
conn.commit()
# 发送邮件 - 高层抽象
smtp = smtplib.SMTP('smtp.gmail.com', 587)
smtp.login('me@gmail.com', 'password')
smtp.sendmail(...)
return "User created"
# ✅ 优秀的函数设计(单一抽象层次)
def register_user(user_data: Dict) -> RegistrationResult:
"""
注册用户 - 高层协调函数
只负责编排,具体细节交给其他函数
"""
# 1. 验证输入(同一抽象层次)
validation_result = validate_user_input(user_data)
if not validation_result.is_valid:
return RegistrationResult.failure(validation_result.errors)
# 2. 检查用户是否存在(同一抽象层次)
if user_exists(user_data['email']):
return RegistrationResult.failure("User already exists")
# 3. 创建用户(同一抽象层次)
user = create_user(user_data)
# 4. 发送欢迎邮件(同一抽象层次)
send_welcome_email(user)
return RegistrationResult.success(user)
def validate_user_input(user_data: Dict) -> ValidationResult:
"""验证用户输入 - 单一职责"""
errors = []
if not user_data.get('email'):
errors.append("Email is required")
elif not is_valid_email(user_data['email']):
errors.append("Invalid email format")
if not user_data.get('password'):
errors.append("Password is required")
elif len(user_data['password']) < 8:
errors.append("Password must be at least 8 characters")
return ValidationResult(is_valid=len(errors) == 0, errors=errors)
def user_exists(email: str) -> bool:
"""检查用户是否存在 - 单一职责"""
# 低层抽象在辅助函数内部
with get_db_connection() as conn:
cursor = conn.cursor()
cursor.execute("SELECT 1 FROM users WHERE email = ?", (email,))
return cursor.fetchone() is not None
def create_user(user_data: Dict) -> User:
"""创建用户 - 单一职责"""
hashed_password = hash_password(user_data['password'])
user = User(
email=user_data['email'],
password_hash=hashed_password,
created_at=datetime.now()
)
with get_db_connection() as conn:
# 保存到数据库...
pass
return user
def send_welcome_email(user: User):
"""发送欢迎邮件 - 单一职责"""
# 邮件发送细节...
pass
函数参数设计:
# ❌ 参数过多
def create_order(user_id, product_ids, quantities, prices, shipping_address, billing_address, coupon_code, gift_wrap):
pass
# ✅ 使用数据类封装参数
@dataclass
class OrderRequest:
user_id: str
items: List[OrderItem]
shipping_address: Address
billing_address: Address
coupon_code: Optional[str] = None
gift_wrap: bool = False
def create_order(request: OrderRequest) -> Order:
pass
# ✅ 使用建造者模式处理复杂参数
class OrderBuilder:
def __init__(self, user_id: str):
self.user_id = user_id
self.items = []
self.shipping_address = None
self.coupon_code = None
def add_item(self, product_id: str, quantity: int, price: Decimal) -> 'OrderBuilder':
self.items.append(OrderItem(product_id, quantity, price))
return self
def ship_to(self, address: Address) -> 'OrderBuilder':
self.shipping_address = address
return self
def with_coupon(self, coupon_code: str) -> 'OrderBuilder':
self.coupon_code = coupon_code
return self
def build(self) -> Order:
return create_order(self)
# 使用
order = OrderBuilder("user_123") \
.add_item("product_1", 2, Decimal('19.99')) \
.add_item("product_2", 1, Decimal('49.99')) \
.ship_to(Address(...)) \
.with_coupon("SAVE10") \
.build()
2.3 注释的最佳实践
注释不是用来弥补坏代码的。好的代码应该是自解释的,注释用来解释"为什么"而不是"是什么"。
# ❌ 糟糕的注释(重复代码)
# 将价格乘以数量得到小计
subtotal = price * quantity # 这行代码已经很清楚
# 循环遍历订单项
for item in order.items: # 循环,很明显
# 增加总价
total += item.price # 增加,也很明显
# ✅ 有用的注释(解释为什么)
# 使用Decimal而不是float来避免浮点数精度问题
price = Decimal(str(raw_price))
# 用户可能在多个设备同时登录,所以使用乐观锁
UPDATE inventory SET quantity = quantity - %s, version = version + 1
WHERE product_id = %s AND version = %s
# 临时方案:由于支付网关的bug,需要将金额向上取整到分
# TODO(zhangsan): 支付网关修复后移除这个hack
amount = amount.quantize(Decimal('0.01'), rounding=ROUND_UP)
# 为什么选择这种算法:用户量在百万级别,布隆过滤器可以在O(1)时间内判断,
# 且内存占用只需要约10MB,如果使用Set需要数百MB
def is_duplicate_user(user_id: str) -> bool:
return bloom_filter.contains(user_id)
# 文档注释(API文档)
def calculate_shipping_cost(
weight: Decimal,
destination: Address,
method: ShippingMethod
) -> Decimal:
"""
计算运费
根据商品重量、目的地和配送方式计算运费。
支持标准配送、快速配送和次日达三种方式。
Args:
weight: 商品总重量(千克)
destination: 收货地址,用于计算距离
method: 配送方式
Returns:
运费金额(元)
Raises:
InvalidAddressError: 当地址不支持配送时抛出
WeightLimitExceededError: 当重量超过限制时抛出
Example:
>>> cost = calculate_shipping_cost(
... weight=Decimal('2.5'),
... destination=Address(city="Beijing"),
... method=ShippingMethod.EXPRESS
... )
>>> print(cost)
23.50
"""
pass
2.4 错误处理
优秀的代码能够优雅地处理错误,而不是崩溃或隐藏错误。
# ❌ 糟糕的错误处理
def divide(a, b):
return a / b # 如果b=0会崩溃
def get_user(user_id):
return users[user_id] # 如果key不存在会崩溃
def parse_json(data):
return json.loads(data) # 如果data不是有效JSON会崩溃
# ✅ 优秀的错误处理
from typing import Optional, Union
from dataclasses import dataclass
# 方式1:返回Optional/Result类型
def divide(a: float, b: float) -> Optional[float]:
"""安全除法,b为0时返回None"""
if b == 0:
return None
return a / b
# 方式2:返回Result类型(类似Rust的Result)
@dataclass
class Result[T, E]:
success: bool
value: Optional[T] = None
error: Optional[E] = None
@classmethod
def ok(cls, value: T) -> 'Result[T, E]':
return cls(success=True, value=value)
@classmethod
def err(cls, error: E) -> 'Result[T, E]':
return cls(success=False, error=error)
def unwrap(self) -> T:
if not self.success:
raise ValueError(f"Called unwrap on error result: {self.error}")
return self.value
def unwrap_or(self, default: T) -> T:
return self.value if self.success else default
def divide_result(a: float, b: float) -> Result[float, str]:
if b == 0:
return Result.err("Division by zero")
return Result.ok(a / b)
# 使用
result = divide_result(10, 2)
if result.success:
print(f"Result: {result.value}")
else:
print(f"Error: {result.error}")
# 方式3:使用自定义异常
class DivisionError(Exception):
"""除法运算错误"""
pass
def divide_raise(a: float, b: float) -> float:
if b == 0:
raise DivisionError("Cannot divide by zero")
return a / b
# 调用方处理异常
try:
result = divide_raise(10, 0)
except DivisionError as e:
logger.error(f"Division failed: {e}")
result = 0
# 方式4:使用装饰器统一处理
def handle_errors(default_value=None, log_error=True):
"""错误处理装饰器"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
if log_error:
logging.error(f"Error in {func.__name__}: {e}")
if default_value is not None:
return default_value
raise
return wrapper
return decorator
@handle_errors(default_value=0, log_error=True)
def risky_operation(data):
# 可能抛出异常的操作
return 1 / data['value']
2.5 代码格式化与风格
一致的代码风格让团队协作更顺畅。
# 使用工具自动格式化
# - Black: 自动格式化Python代码
# - isort: 自动排序import
# - ruff: 快速linting
# .pre-commit-config.yaml 示例
repos:
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
language_version: python3
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: ["--profile", "black"]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.270
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
# 格式化后的代码示例
# 导入分组:标准库 → 第三方库 → 本地模块
import json
import sys
from datetime import datetime
from typing import Dict, List, Optional
import pandas as pd
import requests
from fastapi import FastAPI, HTTPException
from myapp.models import Order, User
from myapp.utils import calculate_total, validate_email
def function_with_proper_formatting(
param1: str,
param2: int,
param3: Optional[Dict] = None,
param4: List[str] = None
) -> Dict[str, Any]:
"""函数文档字符串"""
if param2 > 100:
return {
"status": "error",
"message": "Parameter too large"
}
result = {
"param1": param1,
"param2": param2,
"timestamp": datetime.now().isoformat()
}
return result