【问题标题】:How can I add a required argument to existing python function using a decorator?如何使用装饰器向现有 python 函数添加必需的参数?
【发布时间】:2013-11-12 17:29:55
【问题描述】:

所以,我想修改 json.loads() 函数以接受新的关键字参数,但不要让它只是 kwargs 的一部分。 换句话说,我希望它成为函数签名的显式部分。

这是我对如何做到这一点的猜测。 有更好的方法吗?

def json_to_python_syntax(json_method):
    """
    Translate JSON-conforming key names to Pythonic standards on dict.

    The goal of this decorator is to add a standard keyword parameter
    'convert_syntax' onto the method.  But, I'm not sure how to do this.

    """
    @wraps(json_method)
    def wrapper(json_string, convert_syntax=False, **kwargs):
        pythonic_dict = dict()
        json_syntax_dict = json_method(json_string, **kwargs)

        if not convert_syntax:
            return json_syntax_dict

        for key, value in json_syntax_dict.iteritems():
            for json_syntax in re.finditer(r'[A-Z]', key):
                key = key.replace(
                    json_syntax.group(), '_' + json_syntax.group()[0].lower())
            pythonic_dict[key] = value
        return pythonic_dict

    return wrapper

我对这种方法的担心是它会在 json.loads 中使用预期的关键字参数顺序(它使 convert_syntax 成为 json 字符串之后的第一个预期参数),并且可能会在较大的范围内混淆对 json.loads 的其他调用假定标准顺序的程序。

【问题讨论】:

  • 那有什么问题呢?
  • 这到底有什么问题?装饰器所做的只是为给定的装饰函数返回一个函数(它甚至可以是原始函数,未更改)。您返回了一个有效的函数对象,其签名符合您的需求。
  • 最好的办法是不做。您的代码现在依赖于“魔法”,这与其他开发人员期望 json.loads 工作的方式不同。
  • @Martijn,感谢 cmets 伙计们。我忽略了问题中最重要的部分,有更好的方法吗?影响更大程序中对 json.loads 的其他调用。
  • 您根本没有将关键字参数传递给json_method,所以我不明白这是怎么回事。无论如何,在签名中添加参数作为最后一个元素的唯一方法是使用**kwargs,因为它们必须是最后一个参数。您必须显式插入函数的每个参数。

标签: python decorator


【解决方案1】:

看到您的更改破坏了 json.loads 的预期签名,并且您担心它会破坏其他依赖于原始签名的代码,我同意 Simeon Visser 的观点,看来您根本不应该这样做.

只有您编写的代码才能正确调用您的新方法,那么为什么不给您的方法起一个不同的名称,而不是修饰现有方法呢?如果您想阻止其他代码在没有convert_syntax 标志的情况下调用此方法,只需完全避免导入json 模块,而是导入包装json 模块的json 库。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-23
    • 2021-03-28
    • 2014-07-21
    • 2013-02-24
    • 1970-01-01
    • 2013-09-14
    • 2020-09-05
    • 2020-02-06
    相关资源
    最近更新 更多