
编写高质量的Python函数是提升代码质量的关键。本文将介绍25个实用的Python函数编写技巧及示例代码,帮助开发者写出更专业、更易维护的代码。
函数名应该清晰表达其功能,遵循Python的命名规范(snake_case)。如:
# 好例子
def calculate_monthly_payment(principal, interest_rate, years):
"""计算每月还款金额"""
monthly_rate = interest_rate / 12 / 100
months = years * 12
return principal * monthly_rate / (1 - (1 + monthly_rate) ** -months)
# 差例子
def calc(p, i, y):
return p * i / 12 / 100 / (1 - (1 + i / 12 / 100) ** (-y * 12))每个函数应该只做一件事,保持功能单一。
# 违反单一职责
def process_order(order):
validate_order(order)
update_inventory(order)
charge_customer(order)
send_confirmation(order)
# 符合单一职责
def process_order(order):
validated_order = validate_order(order)
updated_inventory = update_inventory(validated_order)
receipt = charge_customer(updated_inventory)
send_confirmation(receipt)默认参数可以使函数调用更简洁,但要避免使用可变对象作为默认值。
def create_user(name, email, is_admin=False, is_active=True):
"""创建用户账户"""
return {
'name': name,
'email': email,
'is_admin': is_admin,
'is_active': is_active
}
# 正确使用可变默认参数
def append_to_list(value, target_list=None):
if target_list is None:
target_list = []
target_list.append(value)
return target_listPython支持类型注解,可以提升代码可读性和IDE支持。
from typing import Optional, List, Dict
def analyze_text(
text: str,
stop_words: Optional[List[str]] = None
) -> Dict[str, int]:
"""分析文本词频"""
if stop_words is None:
stop_words = []
words = [word.lower() for word in text.split() if word.lower() not in stop_words]
return {word: words.count(word) for word in set(words)}良好的文档字符串应该说明函数的作用、参数、返回值和可能的异常。
def calculate_discount(price: float, discount_percent: float) -> float:
"""计算商品折扣后的价格
Args:
price: 商品原价,必须大于0
discount_percent: 折扣百分比(0-100)
Returns:
折扣后的价格
Raises:
ValueError: 如果价格或折扣百分比无效
"""
if price <= 0:
raise ValueError("价格必须大于0")
if not 0 <= discount_percent <= 100:
raise ValueError("折扣百分比必须在0-100 return price * (1 - discount_percent / 100)装饰器可以非侵入式地扩展函数功能。
import time
from functools import wraps
def time_it(func):
"""测量函数执行时间的装饰器"""
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f"{func.__name__}执行时间: {end - start:.6f}秒")
return result
return wrapper
@time_it
def slow_function():
"""模拟耗时操作"""
time.sleep(1)
return "完成"捕获能处理的异常,并提供有意义的错误信息。
class InvalidDataError(Exception):
"""自定义数据验证异常"""
pass
def process_data(data: dict) -> float:
"""处理数据并返回计算结果"""
try:
validate_data(data)
result = complex_calculation(data)
except InvalidDataError as e:
print(f"数据无效: {e}")
raise # 重新抛出给调用者处理
except (TypeError, ValueError) as e:
print(f"计算错误: {e}")
return 0.0 # 提供默认值
else:
return result
finally:
cleanup_resources() # 确保资源释放生成器可以节省内存,特别适合处理大数据集。
def read_large_file(file_path: str):
"""逐行读取大文件"""
with open(file_path, 'r', encoding='utf-8') as f:
for line in f:
yield line.strip()
def process_logs(log_file: str):
"""处理日志文件,过滤出错误日志"""
for line in read_large_file(log_file):
if 'ERROR' in line:
yield extract_error_details(line)函数参数数量应控制在5个以内,过多参数会降低可读性并增加测试复杂度。相关参数应分组为对象或使用 **kwargs 。
# 参数过多的问题示例
def create_user(name, email, phone, address, birth_date, gender, is_admin=False):
# 难以维护和调用
pass
# 改进后的版本
def create_user(user_details, account_settings=None):
"""
Args:
user_details: UserDetails对象,包含个人信息
account_settings: 可选账户设置字典
"""
if account_settings is None:
account_settings = {}
# 实现代码使用 with 语句和上下文管理器协议安全管理资源,避免资源泄漏。
class DatabaseConnection:
def __init__(self, connection_string):
self.conn_string = connection_string
self.connection = None
def __enter__(self):
self.connection = connect_to_db(self.conn_string)
return self.connection
def __exit__(self, exc_type, exc_val, exc_tb):
if self.connection:
self.connection.close()
if exc_type is not None:
logger.error(f"数据库错误: {exc_val}")
return False # 不抑制异常
# 使用示例
with DatabaseConnection("mysql://user:pass@localhost/db") as conn:
results = conn.execute_query("SELECT * FROM users")Python虽然不是纯函数式语言,但支持高阶函数、不可变数据等函数式特性。
from functools import reduce
from operator import mul
def factorial(n):
"""使用reduce实现阶乘"""
return reduce(mul, range(1, n+1), 1)
def process_data_pipeline(data, *transforms):
"""函数组合处理数据管道"""
return reduce(lambda val, fn: fn(val), transforms, data)
# 使用示例
cleaned_data = process_data_pipeline(
raw_data,
remove_duplicates,
normalize_values,
apply_scaling
)使用函数作为一等公民实现策略模式,避免复杂的类层次结构。
def linear_search(items, key):
"""线性搜索策略"""
for i, item in enumerate(items):
if item == key:
return i
return -1
def binary_search(sorted_items, key):
"""二分搜索策略"""
low, high = 0, len(sorted_items) - 1
while low <= high:
mid = (low + high) // 2
if sorted_items[mid] < key:
low = mid + 1
elif sorted_items[mid] > key:
high = mid - 1
else:
return mid
return -1
def get_search_strategy(strategy_name):
"""策略工厂函数"""
strategies = {
'linear': linear_search,
'binary': binary_search
}
return strategies.get(strategy_name, linear_search)
# 使用示例
search = get_search_strategy('binary')
index = search(sorted_data, target_value)使用 functools.partial 创建预设参数的函数变体。
from functools import partial
def power(base, exponent):
"""计算幂"""
return base ** exponent
# 创建特定函数变体
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
sqrt = partial(power, exponent=0.5)
# 使用示例
print(square(4)) # 16
print(cube(3)) # 27
print(sqrt(16)) # 4.0使用装饰器实现基于参数类型的多分派。
from functools import singledispatch
@singledispatch
def process(data):
"""默认处理"""
raise NotImplementedError("未实现的数据类型处理")
@process.register
def _(data: dict):
"""处理字典"""
return {k: process(v) for k, v in data.items()}
@process.register
def _(data: list):
"""处理列表"""
return [process(item) for item in data]
@process.register
def _(data: str):
"""处理字符串"""
return data.strip().upper()
@process.register
def _(data: int):
"""处理整数"""
return data * 2
# 使用示例
mixed_data = [1, " hello ", {"key": [2, " world "]}]
print(process(mixed_data))
# [2, 'HELLO', {'key': [4, 'WORLD']}]使用装饰器自动缓存函数结果,优化重复计算。
from functools import lru_cache
import hashlib
def memoize_by_args(maxsize=128):
"""基于参数哈希的记忆化装饰器"""
def decorator(func):
cache = {}
@wraps(func)
def wrapper(*args, **kwargs):
# 创建参数哈希键
arg_hash = hashlib.md5()
for arg in args:
arg_hash.update(str(arg).encode())
for k, v in sorted(kwargs.items()):
arg_hash.update(f"{k}={v}".encode())
key = arg_hash.hexdigest()
if key not in cache:
cache[key] = func(*args, **kwargs)
if len(cache) > maxsize:
cache.pop(next(iter(cache)))
return cache[key]
wrapper.clear_cache = cache.clear
return wrapper
return decorator
@memoize_by_args(maxsize=1000)
def expensive_computation(params):
"""耗时的计算函数"""
# 复杂计算过程
return result为异步函数添加健壮的错误处理和重试机制。
import asyncio
from functools import wraps
def async_retry(max_attempts=3, delays=(1, 3, 5)):
"""异步函数重试装饰器"""
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
last_error = None
for attempt in range(max_attempts):
try:
return await func(*args, **kwargs)
except Exception as e:
last_error = e
if attempt < max_attempts - 1:
delay = delays[attempt] if attempt < len(delays) else delays[-1]
await asyncio.sleep(delay)
raise last_error if last_error else RuntimeError("未知错误")
return wrapper
return decorator
@async_retry(max_attempts=5, delays=(1, 2))
async def fetch_api_data(url):
"""获取API数据,失败时自动重试"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
response.raise_for_status()
return await response.json()使用生成器构建数据处理管道,实现高效流式处理。
def filter_data(predicate):
"""数据过滤生成器"""
def generator(iterable):
for item in iterable:
if predicate(item):
yield item
return generator
def transform_data(mapper):
"""数据转换生成器"""
def generator(iterable):
for item in iterable:
yield mapper(item)
return generator
def pipeline(*stages):
"""组合多个处理阶段"""
def runner(iterable):
return reduce(lambda data, stage: stage(data), stages, iterable)
return runner
# 使用示例
data_processing = pipeline(
filter_data(lambda x: x['value'] > 0),
transform_data(lambda x: {**x, 'value': x['value'] * 2}),
transform_data(lambda x: {**x, 'processed': True})
)
for processed_item in data_processing(raw_data_stream):
store_result(processed_item)在运行时动态创建和修改函数,实现高度灵活性。
def create_math_function(operation):
"""动态创建数学运算函数"""
if operation == 'add':
def math_func(a, b):
return a + b
elif operation == 'subtract':
def math_func(a, b):
return a - b
elif operation == 'multiply':
def math_func(a, b):
return a * b
elif operation == 'divide':
def math_func(a, b):
return a / b if b != 0 else float('nan')
else:
raise ValueError(f"未知操作: {operation}")
# 添加元数据
math_func.__name__ = f"math_{operation}"
math_func.__doc__ = f"执行 {operation} 运算"
return math_func
# 使用示例
add = create_math_function('add')
print(add(3, 5)) # 8
print(add.__name__) # 'math_add'对于计算密集型函数,可以使用缓存提高性能。
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n: int) -> int:
"""计算斐波那契数列"""
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
# 第一次调用会计算
print(fibonacci(50))
# 后续调用直接从缓存获取
print(fibonacci(50))闭包可以捕获和记住函数定义时的环境。
def create_counter(start=0):
"""创建一个计数器闭包"""
count = start
def counter():
nonlocal count
count += 1
return count
return counter
# 使用示例
counter1 = create_counter(10)
print(counter1()) # 11
print(counter1()) # 12
counter2 = create_counter()
print(counter2()) # 1将多个简单函数组合成复杂操作。
def compose(*functions):
"""组合多个函数"""
def inner(arg):
result = arg
for func in reversed(functions):
result = func(result)
return result
return inner
# 定义几个简单函数
def add_one(x):
return x + 1
def square(x):
return x * x
def double(x):
return x * 2
# 组合函数
complex_operation = compose(add_one, square, double)
# 相当于 double(square(add_one(3)))
print(complex_operation(3)) # 32functools.partial可以创建预设部分参数的新函数。
from functools import partial
def power(base, exponent):
"""计算幂"""
return base ** exponent
# 创建平方函数
square = partial(power, exponent=2)
# 创建立方函数
cube = partial(power, exponent=3)
print(square(5)) # 25
print(cube(3)) # 27对于简单的单行函数,可以使用lambda表达式。
# 对列表中的每个元素应用操作
numbers = [1, 2, 3, 4, 5]
# 使用lambda计算平方
squares = list(map(lambda x: x**2, numbers))
# 使用lambda过滤偶数
evens = list(filter(lambda x: x % 2 == 0, numbers))
# 使用lambda排序,按绝对值大小
sorted_numbers = sorted([-3, 2, -1, 4, 0], key=lambda x: abs(x))对于常见操作,operator模块提供了更高效的实现。
from operator import itemgetter, attrgetter, methodcaller
# 按字典的某个键排序
data = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}]
sorted_by_age = sorted(data, key=itemgetter('age'))
# 按对象属性排序
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
people = [Person('Alice', 25), Person('Bob', 30)]
sorted_people = sorted(people, key=attrgetter('age'))
# 调用对象方法
uppercase_names = list(map(methodcaller('upper'), ['alice', 'bob']))Python引入enum模块,可以创建更可读的常量。
from enum import Enum, auto
class Color(Enum):
"""颜色枚举"""
RED = auto()
GREEN = auto()
BLUE = auto()
def get_color_name(color: Color) -> str:
"""获取颜色名称"""
if color == Color.RED:
return "红色"
elif color == Color.GREEN:
return "绿色"
elif color == Color.BLUE:
return "蓝色"
else:
raise ValueError("未知颜色")
# 使用示例
print(get_color_name(Color.GREEN)) # "绿色"Python函数编写技巧涵盖了从基础到高级的多个方面,掌握这些技巧可以帮助编写出更专业、更易维护的Python代码。好的函数应该像一段好的散文——清晰、简洁、目的明确:
1、明确意图:每个函数应有一个清晰单一的目的;
2、优雅实现:善用Python特性而非强行移植其他语言模式;
3、考虑边界:处理异常情况,设计防御性代码;
4、文档优先:编写有意义的文档字符串和类型注解;
5、性能意识:在简单性和效率间取得平衡;
“无他,惟手熟尔”!有需要就用起来。
如果你觉得这篇文章有用,欢迎点赞、转发、收藏、留言、推荐❤!
本文分享自 Nicholas与Pypi 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!