Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 具有位置参数和常用命名参数的函数的装饰器_Python_Python 2.7_Decorator_Keyword Argument - Fatal编程技术网

Python 具有位置参数和常用命名参数的函数的装饰器

Python 具有位置参数和常用命名参数的函数的装饰器,python,python-2.7,decorator,keyword-argument,Python,Python 2.7,Decorator,Keyword Argument,我有一组函数/方法,它们都有不同的位置参数集,在某些情况下还有关键字参数,但共享一个名为lane_type的字符串参数。它可以是位置参数或关键字参数。 由于设计缺陷(指控有罪),不同位置的相同值可能在字符串中有大写字母。因此,为了进行比较,我必须将其转换为小写。 最终,我决定尝试通过装饰师进行转换: def lt_dec(func): def _lt_lower(**kwargs): kwargs['lane_type'] = kwargs['lane_type'].lo

我有一组函数/方法,它们都有不同的位置参数集,在某些情况下还有关键字参数,但共享一个名为lane_type的字符串参数。它可以是位置参数或关键字参数。 由于设计缺陷(指控有罪),不同位置的相同值可能在字符串中有大写字母。因此,为了进行比较,我必须将其转换为小写。 最终,我决定尝试通过装饰师进行转换:

def lt_dec(func):
    def _lt_lower(**kwargs):
        kwargs['lane_type'] = kwargs['lane_type'].lower()
        return func(**kwargs)
    return _lt_lower
当然,我尝试过测试,但失败了:

In [38]: @lt_dec
def test1(lane_type):
    print lane_type
   ....:     

In [39]: test1('Solid')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/homes/markg/<ipython-input-39-bb6cef5c7fad> in <module>()
----> 1 test1('Solid')

TypeError: _lt_lower() takes exactly 0 arguments (1 given)
来自另一个类的方法:

def __init__(self, points, lane_type, color, side=None):
函数

def lane_weight(lane_type):
当然,对于具有1个参数的函数(我有几个参数),解决方案很简单

def lt_dec(func):
    def _lt_lower(lane_type):
        return func(lane_type)
    return _lt_lower

如上文所述,是否有一个通用的解决方案,可用于所示的所有示例?(我准备接受“否”作为答案)

使用函数定义中的
**kwargs
,您可以将关键字参数(不是位置参数)作为字典:

>>> def lt_dec(func):
...     def _lt_lower(**kwargs):
...         print 'type(kwargs)=', type(kwargs)
...         print 'kwargs=', kwargs
...         kwargs['lane_type'] = kwargs['lane_type'].lower()
...         return func(**kwargs)
...     return _lt_lower
...
>>> @lt_dec
... def test1(lane_type):
...     print lane_type
...
>>> test1(lane_type='Solid')
type(kwargs)= <type 'dict'>
kwargs= {'lane_type': 'Solid'}
solid
更新

使用:


这是一个decorator版本,它通过在装饰时而不是在执行时使用它来减少inspect的影响。执行影响仍然相对较高,但比您提议的原始装饰器低100倍(仅供参考)


谢谢,但这并不能解决我的一般问题。可能没有通用的解决方案吗?@volcano您的问题将通过此答案得到解决,请您详细说明您的通用问题是什么?在问题中@volcano,我添加了一个处理位置和关键字参数的代码。这就是你想要的吗?@volcano,我添加了另一种使用
inspect.getcallargs
@falsetru的方法,喜欢inspect方法;确切地说,它太重了。但我非常赞成这个想法。你帮了大忙“解决方案很简单”-嗯?那代码什么都做不了。。。
>>> def lt_dec(func):
...     def _lt_lower(**kwargs):
...         print 'type(kwargs)=', type(kwargs)
...         print 'kwargs=', kwargs
...         kwargs['lane_type'] = kwargs['lane_type'].lower()
...         return func(**kwargs)
...     return _lt_lower
...
>>> @lt_dec
... def test1(lane_type):
...     print lane_type
...
>>> test1(lane_type='Solid')
type(kwargs)= <type 'dict'>
kwargs= {'lane_type': 'Solid'}
solid
>>> def lt_dec(func):
...     def _lt_lower(*args, **kwargs):
...         if args:
...             args = (args[0].lower(),) + args[1:]
...         elif 'lane_type' in kwargs:
...             kwargs['lane_type'] = kwargs['lane_type'].lower()
...         return func(*args, **kwargs)
...     return _lt_lower
...
>>> @lt_dec
... def test1(lane_type):
...     print lane_type
...
>>> test1('Solid')
solid
>>> test1(lane_type='Solid')
solid
>>> import inspect
>>>
>>> def lt_dec(func):
...     def _lt_lower(*args, **kwargs):
...         kwargs = inspect.getcallargs(func, *args, **kwargs)
...         if 'lane_type' in kwargs:
...             kwargs['lane_type'] = kwargs['lane_type'].lower()
...         return func(**kwargs)
...     return _lt_lower
...
>>> @lt_dec
... def test1(blah, lane_type):
...     print lane_type
...
>>> test1('foo', 'Solid')
solid
>>> test1('foo', lane_type='Solid')
solid
def lane_type_lower(func):

    def _conv_pos(*args, **kwargs):
        args = list(args);
        args[pos] = args[pos].lower()
        return args, kwargs

    def _conv_kw(*args, **kwargs):
        kwargs['lane_type'] = kwargs['lane_type'].lower()
        return args, kwargs

    insp = inspect.getargspec(func)
    try:
        pos = insp.args.index('lane_type')
        conv_func = _conv_pos
    except ValueError:
        conv_func = _conv_kw

    def _lane_type_lower(*args, **kwargs):
        args, kwargs = conv_func(*args, **kwargs)
        return func(*args, **kwargs)

    return _lane_type_lower