Python 带参数的装饰器

首先我们定义一个可以打印日志的装饰器:

python 复制代码
def log(func):
    def wrapper(*args, **kwargs):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

它接受一个函数作为输入,再返回一个函数。我们使用一下这个装饰器

python 复制代码
@log
def now():
    print('2023-8-31')

我们调用一下now函数,它不仅打印当前时间,还会在前面打印一行日志:

@log放到now()函数定义处,相当于执行下列语句:

python 复制代码
now = log(now)

假如我们的装饰器需要传递参数,那么我们需要再把装饰器包起来,俗称套娃

python 复制代码
def log(text):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kwargs)
        return wrapper
    return decorator

我们用一下这个装饰器:

python 复制代码
@log('装饰器参数')
def now():
    print('2023-8-31')

执行

上面装饰器等同于

python 复制代码
now = log('装饰器参数')(now)

log('装饰器参数')返回函数decoratordecorator(now)返回函数wrapper

附录

我在看 lite transformer 的代码的时候发现了一个装饰器:

python 复制代码
def register_model(name):
    """
    New model types can be added to fairseq with the :func:`register_model`
    function decorator.

    For example::

        @register_model('lstm')
        class LSTM(FairseqEncoderDecoderModel):
            (...)

    .. note:: All models must implement the :class:`BaseFairseqModel` interface.
        Typically you will extend :class:`FairseqEncoderDecoderModel` for
        sequence-to-sequence tasks or :class:`FairseqLanguageModel` for
        language modeling tasks.

    Args:
        name (str): the name of the model
    """

    def register_model_cls(cls):
    	#如果函数名字登记过了,报错
        if name in MODEL_REGISTRY:
            raise ValueError('Cannot register duplicate model ({})'.format(name))
        #如果函数不是BaseFairseqModel的子类,报错
        if not issubclass(cls, BaseFairseqModel):
            raise ValueError('Model ({}: {}) must extend BaseFairseqModel'.format(name, cls.__name__))
        #登记一下新函数的名字
        MODEL_REGISTRY[name] = cls
        return cls

    return register_model_cls

可以看到它只有两层,register_model(name)对标上面的log(text)register_model_cls对标上面的decorator,它把一个函数cls传进来,登记一下,再把函数cls传出去,没有wrapper。看一下它是怎么调用的:

python 复制代码
@register_model('transformer_multibranch_v2')
class TransformerMultibranchModel(FairseqEncoderDecoderModel):
    """
    Transformer model from `"Attention Is All You Need" (Vaswani, et al, 2017)
    <https://arxiv.org/abs/1706.03762>`_.

    Args:
        encoder (TransformerEncoder): the encoder
        decoder (TransformerDecoder): the decoder

    The Transformer model provides the following named architectures and
    command-line arguments:

    .. argparse::
        :ref: fairseq.models.transformer_parser
        :prog:
    """

在这里,他把新定义的函数TransformerMultibranchModel作为参数cls传进去登记,给它取名nametransformer_multibranch_v2

相关推荐
薰衣草23331 小时前
力扣——位运算
python·算法·leetcode
两只程序猿1 小时前
数据可视化 | Violin Plot小提琴图Python实现 数据分布密度可视化科研图表
开发语言·python·信息可视化
大模型真好玩2 小时前
架构大突破! DeepSeek-V3.2发布,五分钟速通DeepSeek-V3.2核心特性
人工智能·python·deepseek
玩转C语言和数据结构3 小时前
Jupyter Notebook下载安装使用教程(附安装包,图文并茂)
ide·python·jupyter·anaconda·jupyternotebook·anaconda下载·anaconda安装包
2401_841495643 小时前
【自然语言处理】Universal Transformer(UT)模型
人工智能·python·深度学习·算法·自然语言处理·transformer·ut
CodeCraft Studio3 小时前
借助Aspose.Email,使用 Python 读取 Outlook MSG 文件
前端·python·outlook·aspose·email·msg·python读取msg文件
赵谨言3 小时前
基于python数据挖据的教学监控系统的设计与应用
开发语言·经验分享·python
一只自律的鸡3 小时前
【python】从Hello World到数据类型
开发语言·python
鱼鱼说测试4 小时前
Selenium+python自动化1-环境搭建
python·selenium·自动化
元基时代4 小时前
专业的短视频发布矩阵哪家靠谱
大数据·人工智能·python·矩阵