You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Python类的多个方法强制统一函数签名并复用输入校验?

统一类方法签名与内置输入校验的实现方案

以下是3种常见的实现方案,可根据你的使用场景选择:


方案1:装饰器(最常用、改造成本最低)

用装饰器封装统一的参数默认值、校验逻辑,所有计算方法只需加装饰器即可,无需重复写校验代码。同时搭配ParamSpec可以保留方法的类型签名提示,IDE不会丢失补全能力。

示例代码

from functools import wraps
from typing import Callable, ParamSpec, TypeVar
import pandas as pd

# Python 3.10以下版本可以从typing_extensions导入ParamSpec和TypeVar
P = ParamSpec("P")
R = TypeVar("R", bound=pd.Series)

def calc_method(func: Callable[P, R]) -> Callable[P, R]:
    @wraps(func)
    def wrapper(
        self,
        relativistic: bool = False,
        tol: float = 0.001,
        verbose: int = 0,
        *args, **kwargs
    ) -> R:
        # 内置统一校验逻辑
        if not 0 < tol < 1:
            raise ValueError("tol必须为0到1之间的浮点数")
        if verbose not in (0, 1, 2):
            raise ValueError("verbose仅支持取值0、1、2")
        # 校验通过后执行实际业务逻辑
        return func(self, relativistic=relativistic, tol=tol, verbose=verbose, *args, **kwargs)
    return wrapper

业务方法使用方式

class PhysicsCalculator:
    @calc_method
    def calculate_mass(self, relativistic:bool=False, tol=0.001, verbose:int=0)->pd.Series:
        # 此处仅需写业务逻辑,无需重复校验
        ans = pd.Series([...])
        return ans 

    @calc_method
    def calculate_energy(self, relativistic:bool=False, tol=0.001, verbose:int=0)->pd.Series:
        ans = pd.Series([...])
        return ans 

如果后续需要修改参数默认值、新增校验规则,仅需修改calc_method装饰器即可,所有方法同步生效。


方案2:模板方法(适合校验逻辑复杂、扩展需求多的场景)

把公共的参数处理、校验逻辑封装为类的内部公共方法,具体的计算方法仅需传入业务逻辑实现即可,完全不需要重复处理参数。

示例代码

import pandas as pd
from typing import Callable

class PhysicsCalculator:
    # 公共包装逻辑,统一处理参数、校验
    def _calc_template(self, calc_logic: Callable[[bool, float, int], pd.Series], **kwargs) -> pd.Series:
        # 统一参数默认值
        params = {
            "relativistic": kwargs.get("relativistic", False),
            "tol": kwargs.get("tol", 0.001),
            "verbose": kwargs.get("verbose", 0)
        }
        # 统一校验
        if not 0 < params["tol"] < 1:
            raise ValueError("tol必须为0到1之间的浮点数")
        if params["verbose"] not in (0, 1, 2):
            raise ValueError("verbose仅支持取值0、1、2")
        # 执行业务逻辑
        return calc_logic(**params)

    # 具体业务方法,仅需实现核心逻辑
    def calculate_mass(self, **kwargs) -> pd.Series:
        def _logic(relativistic, tol, verbose):
            # 业务逻辑代码
            return pd.Series([...])
        return self._calc_template(_logic, **kwargs)
    
    def calculate_energy(self, **kwargs) -> pd.Series:
        def _logic(relativistic, tol, verbose):
            # 业务逻辑代码
            return pd.Series([...])
        return self._calc_template(_logic, **kwargs)

方案3:静态签名强制约束(需要配合类型检查工具)

如果需要从代码静态层面强制所有方法符合签名,避免运行时才发现参数写错,可以用Protocol定义方法签名协议,配合mypy等类型检查工具,不符合签名的代码会直接在检查阶段报错。

示例代码

from typing import Protocol
import pandas as pd

# 定义计算方法的签名协议
class CalcMethod(Protocol):
    def __call__(self, relativistic: bool = False, tol: float = 0.001, verbose: int = 0) -> pd.Series: ...

class PhysicsCalculator:
    # 标注所有计算方法的类型为CalcMethod
    calculate_mass: CalcMethod
    calculate_energy: CalcMethod

    # 如果此处参数名、类型、返回值和协议不符,mypy会直接报错
    def calculate_mass(self, relativistic:bool=False, tol=0.001, verbose:int=0)->pd.Series:
        ...

内容的提问来源于stack exchange,提问作者MYK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 06:06:04