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

如何修改被装饰函数帮助文档中的参数签名?

问题描述

我有一个包含方法的类,该方法原本接收两个参数a和b,代码如下:

class Foo:
  def method(self, a, b):
    """Does something"""
    x, y, z = a.x, a.y, b.z
    return do(x, y, z)

在Python REPL中运行help(Foo)时,会显示该方法的参数为self、a、b。

我使用装饰器更新了该类,由装饰器负责解包参数,将x、y、z传入方法,而非原方法自行解包:

def unpack(fn):
  def _unpack(self, a, b):
    x, y, z = a.x, a.y, b.z
    return fn(self, x, y, z)
  return _unpack

class Foo:
  @unpack
  def method(self, x, y, z):
    """Does something"""
    return do(x, y, z)

此时功能正常,但帮助文档显示method = _unpack(self, a, b),信息不够清晰。

使用functools.wraps可以修复文档显示问题,但会导致帮助文档显示方法接收x、y、z三个参数,而实际仍接收a和b两个参数,存在误导。

是否可以修改函数包装器,使其像functools.wraps一样正确获取文档字符串等属性,同时显示包装器接收的参数?
例如,即使被unpack装饰,帮助文档仍显示方法参数为self、a、b。

(我已查看functools.wraps的源码,但不确定它是否能复制函数签名。)


解决方案

要实现既保留原函数的文档字符串等元数据,又让帮助文档显示包装器的参数签名,可通过手动调整包装函数的__signature__属性,结合functools.wraps和inspect模块完成。

具体实现

导入functools和inspect模块后,修改装饰器如下:

import functools
import inspect

def unpack(fn):
    def _unpack(self, a, b):
        x, y, z = a.x, a.y, b.z
        return fn(self, x, y, z)
    
    # 复制原函数的元数据(文档、名称等)
    wrapped = functools.wraps(fn)(_unpack)
    # 手动指定函数签名为包装函数的签名
    wrapped.__signature__ = inspect.signature(_unpack)
    return wrapped

class Foo:
    @unpack
    def method(self, x, y, z):
        """Does something"""
        return do(x, y, z)

效果验证

运行help(Foo)或help(Foo.method)时,会显示:

Help on class Foo in module __main__:

class Foo(builtins.object)
 |  Methods defined here:
 |
 |  method(self, a, b)
 |      Does something
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables (if defined)
 |
 |  __weakref__
 |      list of weak references to the object (if defined)

既保留了原函数的文档字符串,又正确显示了实际接收的参数self、a、b,避免了参数误导。

原理说明

  • functools.wraps(fn)会将原函数的__doc__、__name__等元数据复制给包装函数,解决原装饰器中文档模糊的问题;
  • inspect.signature(_unpack)获取包装函数的参数签名,赋值给wrapped.__signature__后,help()和inspect模块会优先识别这个自定义签名,而非原函数的签名。

该方案兼容Python 3.3及以上版本,__signature__是官方支持的自定义函数签名的标准方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 08:35:23