Skip to main content
Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Function (函数)

🚀 1. 什么是 Python 函数?

函数(function) 是一段可复用的代码块,用来执行特定任务。

函数可以:

  • 接收参数
  • 返回值
  • 内部执行逻辑
  • 封装行为,提高复用性

最基础例子:

def add(a, b):
    return a + b

调用:

add(1, 2)

📌 2. Python 函数的组成语法

def 函数名(参数列表):
    函数体
    return 返回值

例:

def greet(name: str) -> str:
    return f"Hello, {name}"

📌 3. 参数类型(重点)

Python 函数支持 多种参数类型:

3.1 普通位置参数

def add(a, b):
    return a + b

3.2 默认参数

def connect(host="localhost", port=3306):
    ...

3.3 可变参数:*args

def total(*nums):
    return sum(nums)

total(1,2,3)

3.4 关键字可变参数:**kwargs

def debug(**info):
    print(info)

debug(a=1, b=2)

3.5 仅限关键字参数:*

def config(*, debug=False):
    print(debug)

必须写成:

config(debug=True)

3.6 并排组合(非常常见)

def func(a, b, *args, c=1, d=2, **kwargs):
    ...

📌 4. 返回值 return

def foo():
    return 123

多个返回:

def get_info():
    return "jack", 18

name, age = get_info()

返回 None:

def log(msg):
    print(msg)
    # 默认 return None

📌 5. 函数类型(重要)

在 Python 里,函数本质上是对象,类型是:

import types
type(func) == types.FunctionType

函数可以:

  • 赋值
  • 存入 dict
  • 作为参数传递
  • 作为返回值返回

例:

def a():
    print("a")

b = a
b()

📌 6. 函数作为参数(高阶函数)

def apply(func, x):
    return func(x)

def double(n):
    return n * 2

apply(double, 5)  # 10

📌 7. 匿名函数 lambda

square = lambda x: x * x

常用于 map/filter/sorted:

sorted(data, key=lambda x: x["age"])

📌 8. 闭包(非常重要)

闭包 = 内层函数 + 外层作用域变量

def make_adder(n):
    def adder(x):
        return x + n
    return adder

add5 = make_adder(5) add5(10) # 15

📌 9. 装饰器(进阶)

装饰器本质是高阶函数:

def log(func):
    def wrapper(*a, **kw):
        print(f"Run {func.__name__}")
        return func(*a, **kw)
    return wrapper

使用:

@log
def run():
    pass

📌 10. 生成器函数(yield)

普通函数:一次返回 生成器:逐次返回,惰性计算

def gen():
    yield 1
    yield 2

📌 11. 异步函数 async def

async def fetch(url):
    ...

配合 await:

data = await fetch(url)

你的 FastAPI 项目常用的就是 async 函数。

📌 12. 拆包函数参数(*args / **kwargs)

def f(a, b, c):
    ...

args = (1,2,3)
f(*args)

kwargs = {"a":1,"b":2,"c":3}
f(**kwargs)

📌 13. 递归函数

函数调用自己:

def fact(n):
    return 1 if n==0 else n * fact(n-1)

📌 14. Python 函数生命周期、作用域 LEGB

LEGB 规则:

  • Local(局部)
  • Enclosing(外层函数)
  • Global(模块)
  • Built-in(内置)

例:

x = 10  # global

def outer():
    x = 20  # enclosing

    def inner():
        x = 30  # local

📌 15. 函数注解(Type Hint)

def add(a: int, b: int) -> int:
    return a + b

📌 16. ⭐ 函数设计最佳实践

  1. 逻辑小而清晰
  2. 使用类型注解提高可读性
  3. 参数使用 dict 时优先加类型别名:dict[str, Any] 或 TypedDict
  4. 尽量保持函数纯净(无副作用)
  5. 把大函数拆分为多个小函数
  6. 配合装饰器统一异常处理、性能监控、日志
  7. 尽量避免使用全局变量
  8. 输入参数要先校验(你正在做)

📌 17. 函数 vs 类:什么时候用函数?

用函数:

  • 非复杂逻辑
  • 不需要状态
  • 不需要多次复用内部数据
  • utils 工具类中的大部分都可以用函数

用类:

  • 需要保存状态(数据库连接池 / 配置对象)
  • 需要扩展性
  • 需要继承
  • 需要 property、static、class 等丰富接口

📌 18. 小结(强烈建议收藏)

领域 内容
基础 def / 参数 / return
进阶 *args / **kwargs / lambda
高阶 装饰器 / 闭包 / 上下文管理
异步 async / await
惰性 yield 生成器
工程 类型注解 / 函数式编程 / 模块化设计

最佳实践

下面是一份 真正项目级的《Python 定义函数最佳实践(最强完整版)》

同时结合你长期的代码风格(FastAPI + SQLAlchemy + 工具函数为主),给出最实用、最现代、最强类型、可维护性优秀的标准。

内容涵盖:

  • 命名规范
  • 参数设计
  • 返回值
  • 类型注解
  • 文档注释
  • 错误处理
  • 性能优化
  • 函数式工具
  • 模块封装
  • 何时用类、何时用函数

☘️ 1. 函数命名最佳实践

场景 命名方式 示例
动作型函数 动词开头 get_user、save_data
工具函数 动词 + 名词 to_datetime、to_json、map_filter
转换函数 to_ / from_ to_dict、from_row
判断函数 is_ / has_ / should_ is_valid、has_permission
私有函数 前置下划线 _parse_row、_clean_title

✅ 为别人阅读代码时“意图可见”。

☘️ 2. 函数参数设计最佳实践

2.1 少量参数用位置参数,多参数用关键字参数

不好:

def create(x, y, z, a, b):
    ...

好:

def create(*, user, title, content, tags=None):
    ...

关键字参数具有:

  • 可读性好
  • 调用更安全
  • 修改参数顺序时不破坏调用方

2.2 可选参数必须有默认值

def fetch(limit: int | None = None):
    ...

2.3 避免使用可变类型作为默认值(重要!!)

❌ 绝对不要:

def fn(data=[]):
    ...

✅ 使用 None:

def fn(data=None):
    if data is None:
        data = []

2.4 接受不定数量参数时:总是写清类型

from typing import Any

def sum_all(*nums: int) -> int:
    return sum(nums)

☘️ 3. 函数返回值最佳实践

3.1 始终返回明确类型(不要返回多种结构)

不要这样:

def get_user(): 
    return user or False

应该这样:

def get_user() -> User | None:
    return user

3.2 若失败,返回 None 或异常,不要返回 False

✅ 更易读,和类型检查工具兼容:

return None

3.3 返回值为 dict 时,保证键名稳定不变

保持 API 兼容性是非常重要的。

☘️ 4. 类型注解最佳实践(你必须遵守的)

你已经明确要求:

  • Python ≥ 3.12
  • 禁止使用 typing 中的已废弃类型

因此应该遵循:

4.1 使用原生 list/dict,不用 List/Dict

def fn(x: list[str]) -> dict[str, int]:
    ...

4.2 使用 collections.abc 中的类型

from collections.abc import Iterable, Callable

def map_filter(iterable: Iterable[T], func: Callable[[T], R]) -> list[R]:
    ...

4.3 永远写明返回值类型

def run_task(task: Task) -> bool:
    ...

4.4 能用具体类型就不用 Any

例如:

def parse(dt: str) -> datetime.datetime:
    ...

☘️ 5. 文档注释(docstring)最佳实践

请使用 Google 风格或 NumPy 风格,不要使用随意风格。

推荐 Google 风格:

def to_datetime(s: str) -> datetime:
    """
    Convert a datetime string to datetime object.

    Args:
        s: datetime string in "%Y-%m-%d %H:%M:%S" format.

    Returns:
        Parsed datetime object.

    Raises:
        ValueError: if the string cannot be parsed.
    """

☘️ 6. 错误处理最佳实践

❌ 不要这样:

try:
    ...
except Exception:
    return None

你会屏蔽一切异常,不利排查。

✅ 正确做法:捕获明确的异常

try:
    x = int(s)
except ValueError:
    logger.error(...)
    return None

☘️ 7. 性能最佳实践

以下规则非常重要(你的项目用得上):

✅ 使用生成器替代 list

def gen_items():
    for i in range(10):
        yield i

✅ 批量处理用 map/filter(C层实现更快)

cleaned = list(map(clean, rows))

✅ 函数内避免创建重复对象

pattern = re.compile(...)

不要:

re.search("xxx", text)  # 每次都编译

☘️ 8. 函数式工具最佳实践

(你已经开始使用 map_filter,非常棒)

推荐你使用:

  • map_filter
  • filter_map
  • compose
  • pipe
  • safe_get
  • find_first(基于 next)

我们可以封装一个完整模块:utils.functional

☘️ 9. 设计函数时要问的关键问题

每次写函数前,请问自己:

  • 这个函数的唯一职责是什么?(SRP)
  • 需要类型强约束吗?
  • 对调用方是否友好?
  • 是否可以测试?
  • 是否需要文档?
  • 是否必须兼容旧字段?
  • 是否要保证确定性(稳定输出)?

☘️ 10. 何时使用类,何时使用函数?

使用类(Class)——当状态很重要时:

  • 数据库 Session 管理
  • 配置对象
  • 服务对象(Service)
  • 有生命周期逻辑
  • 依赖注入

使用函数(Function)——当操作是无状态时:

  • 文本处理
  • 数据转换
  • 解析器
  • 验证器
  • 工具函数

你已经非常明确:utils 模块适合函数式设计。

🎯 终极总结(可以作为团队代码规范)

  • 函数命名清晰、语义明确
  • 参数使用 keyword-only
  • 默认参数避免可变类型
  • 返回值类型清晰(不要 False 表示失败)
  • 使用类型注解(Python 3.12 风格)
  • 适度使用 map/filter/next 函数式处理
  • 提供有意义的 docstring
  • 避免重复构造对象
  • 工具函数模块化封装