【问题标题】:Parameterized Decorators in PythonPython中的参数化装饰器
【发布时间】:2020-04-15 16:14:35
【问题描述】:

我一直在尝试使用 Python 中的不同类型的装饰器,但我发现很难理解参数化装饰器。 装饰器接受可调用对象并返回可调用对象(在我的情况下可调用函数是一个函数) 在以下代码中:-

def check_non_negative(index):
    def validator(f):
        def wrap(*args):
            if args[index]<0:
                raise ValueError(
                    'Argument {} must be non negative.'.format(index))
            return f(*args)
        return wrap
    return validator

@check_non_negative(1)
def create_list(value,size):
    return [value]*size


create_list('a',3)

在这里,我看到 check_non_negative 不是根据定义的装饰器,而是表现得像一个(在运行期间验证器是实际的装饰器)。 check_non_negative 接受一个整数而不是可调用的,但它的行为类似于装饰器。谁能解释一下原因?

【问题讨论】:

标签: python python-decorators


【解决方案1】:

check_non_negative 按照您的定义从技术上讲并不是装饰器,人们可能会称其为“装饰器工厂”。它返回validator一个装饰器。

基本上只要你有:

@<expression>
def ...

然后&lt;expression&gt; 必须评估为装饰器,即接受单个参数的可调用对象,该参数也是可调用对象。

【讨论】:

  • aaaah.. 对,它是一个装饰器工厂,它返回验证器作为装饰器。谢谢!
【解决方案2】:

当您将参数传递给装饰器函数(即@check_non_negative(1))时,会使用这些参数调用该函数,然后它会返回一个接受并返回一个函数的装饰器(就像您使用 @validator 时没有参数)。

使用类型注释 IMO 更容易理解:

import functools
from typing import cast, Callable, List, TypeVar


_Elem = TypeVar('_Elem')
_Func = TypeVar('_Func', bound=Callable)


def check_non_negative(index: int) -> Callable[[_Func], _Func]:
    def validator(f: _Func) -> _Func:
        @functools.wraps(f)
        def wrap(*args, **kwargs):
            if args[index] < 0:
                raise ValueError(
                    'Argument {} must be non negative.'.format(index))
            return f(*args, **kwargs)
        return cast(_Func, wrap)
    return validator


@check_non_negative(1)
def create_list(value: _Elem, size: int) -> List[_Elem]:
    return [value]*size

所以check_non_negative 接受int 参数,并返回一个函数(validator),该函数接受特定类型的函数(_Func,这里指的是修饰函数的类型,例如create_list ) 并返回相同类型的函数。

【讨论】:

  • 正如 Alex 上面所说,我同意 check_non_integer 是一个装饰器工厂,它为我返回一个验证器。
猜你喜欢
  • 1970-01-01
  • 2014-07-21
  • 1970-01-01
  • 2011-11-21
  • 1970-01-01
  • 2016-09-27
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多