Python 装饰器:TypeError:“装饰器”;为关键字参数获取了多个值<;变量名>&引用;关于函数调用

Python 装饰器:TypeError:“装饰器”;为关键字参数获取了多个值<;变量名>&引用;关于函数调用,python,functional-programming,decorator,python-decorators,Python,Functional Programming,Decorator,Python Decorators,我有一个decorator,它接受一个authToken并提供它用一个用户id装饰的函数。其思想是阻止每个特定于用户的函数查找它们的用户对象 我使用*pargs和**kwargs使装饰器通用,并使用带有任何其他参数的函数 但是,当我调用一个装饰函数时,我得到了一个错误:TypeError:changeUsername()为关键字参数“userId”获取了多个值。 有人知道为什么会这样吗?我在下面粘贴了一个最小的示例 users = ["Name_1", "Name_2", "Name_3"]

我有一个decorator,它接受一个authToken并提供它用一个用户id装饰的函数。其思想是阻止每个特定于用户的函数查找它们的用户对象

我使用*pargs和**kwargs使装饰器通用,并使用带有任何其他参数的函数

但是,当我调用一个装饰函数时,我得到了一个错误:
TypeError:changeUsername()为关键字参数“userId”获取了多个值。

有人知道为什么会这样吗?我在下面粘贴了一个最小的示例

users = ["Name_1", "Name_2", "Name_3"]

def pwapi_auth(func):
    def inner(authToken, *pargs, **kwargs):
        users = {'a':0,
                 'b':1,
                 'c':2}
        userId = users[authToken]
        return func(userId = userId, *pargs, **kwargs)
    return inner

@pwapi_auth
def getUsername(userId):
    return users[userId]

@pwapi_auth
def changeUsername(userId, newName):
    users[userId] = newName

print getUsername('b')
changeUsername('b', 'New_Person') # <-- Error occurs on this call
users=[“Name_1”、“Name_2”、“Name_3”]
def pwapi_认证(功能):
def内部(authToken,*pargs,**kwargs):
用户={'a':0,
“b”:1,
'c':2}
userId=users[authToken]
return func(userId=userId,*pargs,**kwargs)
返回内部
@pwapi_auth
def getUsername(用户ID):
返回用户[userId]
@pwapi_auth
def changeUsername(用户ID,新名称):
用户[userId]=新名称
打印getUsername('b')

在代码段中,changeUsername('b','New_Person')#python会混淆userId的位置参数和关键字参数。在pargs中追加所有参数以解决此问题-

def pwapi_auth(func):
    def inner(authToken, *pargs, **kwargs):
        # ...
        users = {'a':0,
                 'b':1,
                 'c':2}
        userId = users[authToken]
        return func(*((userId,)+pargs), **kwargs)
    return inner
>>> print getUsername('b')
Name_2
>>> changeUsername('b', 'New_Person')
>>> print getUsername('b')
New_Person

你不需要在那里列出清单;只需返回
func(*(userId,)+pargs),**kwargs)
谢谢您的输入@zondo,我正在搜索类似的东西,这是更好的方法。我会更新我的答案谢谢你的回答伙计们-看起来很有效。我现在的问题是:上面的示例(添加到问题的底部)使用了一个不需要编辑parg或pwargs的类——它只是将userId作为位置参数直接放入返回的函数中。为什么这样做,而我原来的示例不起作用?
*((userId,)+pargs)
相当于(比)
*(userId,*pargs)
@zondo你的第二个示例不起作用,你能粘贴工作代码段吗?别担心,我现在已经理解了-超类正在做一些事情来简化。