python - 如何在 Python 2 中将位置参数视为关键字参数

标签 python decorator keyword-argument

对于我正在编写的装饰器,我想操作函数的特定命名参数。考虑以下装饰器:

def square_param(param):
    def func_decorator(func):
        def func_caller(*args,**kwargs):
            kwargs[param] = kwargs[param] * kwargs[param]
            return func(*args,**kwargs)
    return func_caller
return func_decorator

应用于下一个函数:

@square_param('dividend')
def quotient(divisor=1,dividend=0):
    return dividend/divisor

如果将股息作为关键字参数调用,这将起作用,例如:

>>> quotient(dividend=2)
4

但是,当作为位置参数给出时,这将失败。

>>> quotient(3,4)
TypeError: quotient() got multiple values for keyword argument 'dividend'

使用 Python 3 我可以通过强制参数为 always given as a keyword 来解决这个问题:

@square_param('dividend')
def quotient(divisor=1,*,dividend=0):
    return dividend/divisor

但我想支持 Python 2,而且我想对该函数施加尽可能少的限制。

有没有办法可以在我的装饰器中修复此行为?

最佳答案

首先,您的 square_param 装饰器不起作用,因为它不返回函数。它必须是:

def square_param(param):
    def func_decorator(func):
        def func_caller(*args,**kwargs):
            kwargs[param] = kwargs[param] * kwargs[param]
            return func(*args,**kwargs)
        return func_caller
    return func_decorator

现在我采纳了@Dirk 的建议并研究了 inspect模块。您可以通过首先检查参数是否是函数的位置参数之一,然后检查该位置参数是否已指定,然后修改该参数位置来实现。您还需要确保仅在参数作为关键字参数提供时才修改 kwargs。

import inspect

def square_param(param):
    def func_decorator(func):
        def func_caller(*args,**kwargs):
            funparams = inspect.getargspec(func).args
            if param in funparams:
                i = funparams.index(param)
                if len(args) > i:
                    args = list(args)   # Make mutable
                    args[i] = args[i] * args[i]
            if param in kwargs:
                kwargs[param] = kwargs[param] * kwargs[param]
            return func(*args,**kwargs)
        return func_caller
    return func_decorator

关于python - 如何在 Python 2 中将位置参数视为关键字参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6579283/

相关文章:

design-patterns - 具有复合设计模式的装饰器设计模式

python - scikit-learn 中的随机森林解释

python - 有没有办法使用 pymysql 将数据帧插入到 mysql 中?

reactjs - 当 CSS 使用 @import 时 Jest 失败

c# - 关于装饰器和策略模式 C# 的设计 OOP 问题

python - 如何从数据库动态获取表?

ruby - 如何从 C 扩展将关键字传递到 Ruby 方法?

python - 类方法采用 1 个位置参数,但给出了 2 个

python - 关于 Python CSV 格式化的建议

python - 如何避免在此递归函数中使用全局变量并改进我的代码?