【问题标题】:Using Python decorators to enforce standard method signature使用 Python 装饰器强制执行标准方法签名
【发布时间】:2026-01-17 23:35:01
【问题描述】:

我有一个包含很多功能的库。我希望与基本方法模式保持一致。我希望所有方法都将上下文作为第一个参数和默认为 0 的关键字 arg。

library_function(context, ..., default=0)

有没有办法可以使用 python 装饰器来转

bobs_function(foo, bar=None)

进入

bobs_library_function(context, foo, bar=None, default=0)

这样做的目的是为声明库函数提供简写。而不是每次都显式添加上下文和默认值。

【问题讨论】:

  • 你能再澄清一下吗?你的bobs_functionbobs_library_function 的例子是为了说明函数是如何定义,或者它们是如何调用的?如果它们是这样称呼的,那么您希望 context 变量来自哪里?也就是说,如果您将bobs_function(foo, bar=None) 写为函数调用,那么“正确”的解决方案应该在哪里寻找作为第一个参数插入的context
  • 我们的目标是能够创建一个简写来声明测试需要一个上下文和一个默认值。但是您要么必须明确声明该函数将上下文作为输入,要么我必须使用 *args, **kwargs 作为参数,但是将 *args 和 **kwargs 作为输入比手动输入上下文更加繁琐,默认=0

标签: python decorator python-decorators


【解决方案1】:

如果你只允许在你的包装函数中传递关键字参数,你就可以做到这一点:

import functools

def lib(fn):
    @functools.wraps(fn)
    def wrapped(context, default=0, **kwargs):
        print context, default
        return fn(**kwargs)
    return wrapped

@lib
def bobs_function(foo, bar=None):
    print foo
    print bar


bobs_function('context', foo='foo', bar='bar', default='default')

打印:

context default
foo
bar

【讨论】:

    【解决方案2】:

    我对这个问题的观察和思考越多,我就越相信答案是否定的。

    我希望能够从内部 bobs 函数访问上下文和默认值。希望我能想出一个方便的速记,以确保我编写的方法签名符合约定。

    问题是我必须提前声明bob_function 采用的参数。如果它需要一个位置参数,那么添加一个新的位置参数会搞砸一切。

    所以我第一个想到

    @library_function
    def bobs_function(foo, bar=None):
         ....
    

    神奇地改变方法签名是行不通的。

    我的下一个想法是扭转它

    @library_function(foo, bar=None)
    def bobs_function(*args, **kwargs):
        ...
    

    但这在语法上甚至都不正确。我不得不将我的变量从 args 和 Charges 中剔除,结果令人不快。

    所以总结一下我的问题。如果我想使用上下文,我必须将其传入。我无法修改bobs_function 的实际声明参数,所以我可以传入上下文的唯一方法是使用 *args **kwargs,这更令人不快不仅仅是打字

    bobs_library_function(context, foo, bar=None, default=0)
    

    开始。

    【讨论】:

    • 不要使用答案来更好地解释您的问题。评论和修改(或删除您的问题)并评论其他答案以说明什么是误解。正如您自己已经理解的那样,您需要的定义是错误的,但您没有在问题中提及它:也许在这种情况下,问题将被否决并关闭。
    • 我不是要解释这个问题。我试图解释答案。答案是不。你可以改变传递给函数的值,你可以包装函数,你可以用一个新函数完全替换一个函数,但是你不能做的是改变一个函数的声明参数。除非明确声明或以 * / ** 方式声明它们,否则您不能使用上下文或默认值,这会给函数编写器带来更多工作。问题是是否有可能,答案是否定的。
    • 在原始函数中而不是在包装函数中提到使用上下文和默认值的问题在哪里?