首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python将args转换为kwargs

Python将args转换为kwargs
EN

Stack Overflow用户
提问于 2009-05-06 18:14:35
回答 7查看 13.6K关注 0票数 28

我正在编写一个装饰器,它需要在调用它正在装饰的函数之前调用其他函数。修饰的函数可能有位置参数,但修饰程序将调用的函数只能接受关键字参数。有没有人有一个方便的方法将位置参数转换为关键字参数?

我知道我可以获得修饰函数的变量名列表:

代码语言:javascript
复制
>>> def a(one, two=2):
...    pass

>>> a.func_code.co_varnames
('one', 'two')

但是我不知道如何区分什么是按位置传递的,什么是关键字。

我的装饰器看起来像这样:

代码语言:javascript
复制
class mydec(object):
    def __init__(self, f, *args, **kwargs):
        self.f = f

    def __call__(self, *args, **kwargs):
        hozer(**kwargs)
        self.f(*args, **kwargs)

除了比较kwargs和co_varnames,向kwargs添加任何不在其中的东西,并期待最好的结果之外,还有其他方法吗?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-05-07 07:37:01

注意-- co_varnames将包括局部变量和关键字。这可能无关紧要,因为zip会截断较短的序列,但是如果您传递了错误数量的参数,可能会导致混乱的错误消息。

使用func_code.co_varnames[:func_code.co_argcount]可以避免这种情况,但最好使用inspect模块。即:

代码语言:javascript
复制
import inspect
argnames, varargs, kwargs, defaults = inspect.getargspec(func)

您可能还希望处理函数定义**kwargs*args的情况(即使只是在与装饰器一起使用时引发异常)。如果设置了这些变量,则getargspec的第二个和第三个结果将返回它们的变量名,否则它们将为None。

票数 9
EN

Stack Overflow用户

发布于 2009-05-06 19:00:33

任何以位置传递的arg都将被传递给*args。任何作为关键字传递的arg都将被传递给**kwargs。如果您有位置参数、值和名称,则可以执行以下操作:

代码语言:javascript
复制
kwargs.update(dict(zip(myfunc.func_code.co_varnames, args)))

将它们全部转换为关键字参数。

票数 21
EN

Stack Overflow用户

发布于 2013-10-23 15:31:19

如果您使用的是PythonPython2.7,inspect.getcallargs()会为您提供开箱即用的解决方案。您只需将修饰函数作为第一个参数传递给它,然后将其余的参数完全按照您计划调用它的方式传递。示例:

代码语言:javascript
复制
>>> def f(p1, p2, k1=None, k2=None, **kwargs):
...     pass
>>> from inspect import getcallargs

我计划使用f('p1', 'p2', 'p3', k2='k2', extra='kx1') (请注意,k1将作为p3进行位置传递),所以...

代码语言:javascript
复制
>>> call_args = getcallargs(f, 'p1', 'p2', 'p3', k2='k2', extra='kx1')
>>> call_args
{'p2': 'p2', 'k2': 'k2', 'k1': 'p3', 'p1': 'p1', 'kwargs': {'extra': 'kx1'}}

如果你知道装饰的函数不会使用**kwargs,那么这个键就不会出现在字典中,你就完成了(我假设没有*args,因为这会打破所有东西都有名称的要求)。如果您有**kwargs,就像我在本例中一样,并希望将它们包含在其余的命名参数中,则需要多加一行:

代码语言:javascript
复制
>>> call_args.update(call_args.pop('kwargs'))
>>> call_args
{'p2': 'p2', 'k2': 'k2', 'k1': 'p3', 'p1': 'p1', 'extra': 'kx1'}

更新:对于Python >= 3.3,请参阅inspect.Signature.bind()和相关的inspect.signature function,了解类似于inspect.getcallargs() (但比inspect.getcallargs()更健壮)的功能。

票数 18
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/830937

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档