简体   繁体   English

装饰员与参数

[英]Decorator with parameters

Can you explain me how the following decorator works: 你能解释一下以下装饰器是如何工作的:

def set_ev_cls(ev_cls, dispatchers=None):
    def _set_ev_cls_dec(handler):
        if 'callers' not in dir(handler):
            handler.callers = {}
        for e in _listify(ev_cls):
            handler.callers[e] = _Caller(_listify(dispatchers), e.__module__)
        return handler
    return _set_ev_cls_dec


@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def _switch_features_handler(self, ev):
    datapath = ev.msg.datapath
    ....

Please, don't go into details on what's going on inside the function. 请不要详细了解该功能内部的内容。 I'm interested in how the decorator with parameters wrap methods here. 我对带有参数的装饰器在这里包装方法感兴趣。 By the way, it's a code snippet from Ryu (event registration mechanism). 顺便说一下,这是Ryu(事件注册机制)的代码段。

Thank you in advance 先感谢您

First, a decorator is just a function that gets called with a function. 首先,装饰器只是一个用函数调用的函数。 In particular, the following are (almost) the same thing: 特别是,以下是(几乎)相同的事情:

@spam
def eggs(arg): pass

def eggs(arg): pass
eggs = spam(eggs)

So, what happens when the decorator takes parameters? 那么,当装饰器获取参数时会发生什么? Same thing: 一样:

@spam(arg2)
def eggs(arg): pass

def eggs(arg): pass
eggs = spam(arg2)(eggs)

Now, notice that the function _set_ev_cls_dec , which is ultimately returned and used in place of _switch_features_handler , is a local function, defined inside the decorator. 现在,请注意函数_set_ev_cls_dec (最终返回并用于代替_switch_features_handler )是一个局部函数,在装饰器内定义。 That means it can be a closure over variables from the outer function—including the parameters of the outer function. 这意味着它可以封闭外部函数的变量,包括外部函数的参数。 So, it can use the handler argument at call time, plus the ev_cls and dispatchers arguments that it got at decoration time. 因此,它可以在调用时使用handler参数,以及它在装饰时获得的ev_clsdispatchers参数。

So: 所以:

  • set_ev_cls_dev creates a local function and returns a closure around its ev_cls and dispatchers arguments, and returns that function. set_ev_cls_dev创建一个本地函数,并在其ev_clsdispatchers参数周围返回一个闭包,并返回该函数。
  • That closure gets called with _switch_features_handler as its parameter, and it modifies and returns that parameter by adding a callers attribute, which is a dict of _Caller objects built from that closed-over dispatchers parameter and keyed off that closed-over ev_cls parameter. 那封被称为与_switch_features_handler作为它的参数,它会修改和添加一个返回参数callers属性,它是一个字典_Caller从封闭在建对象dispatchers参数和键控关闭该封闭了ev_cls参数。

Explain how it works without detailing what's going on inside? 在不详细说明内部发生什么的情况下解释其工作原理? That kind of sounds like "explain without explaining," but here's a rough walkthrough: 这种听起来像“解释没有解释”,但这是一个粗略的演练:

  1. Think of set_ev_cls as a factory for decorators. set_ev_cls视为装饰器的工厂。 It's there to catch the arguments at the time the decorator is invoked: 它是在调用装饰器时捕获参数的:

     @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) 

    And return a function, _set_ev_cls_dec that has its variables bound to: 并返回一个函数_set_ev_cls_dec ,该函数的变量绑定到:

     ev_cls = ofp_event.EventOFPSwitchFeatures dispatchers = CONFIG_DISPATCHER 

    Or put another way, you now have a 'customized' or 'parametrized' dispatcher that's logically equivalent to: 换句话说,您现在拥有一个“定制”或“参数化”调度程序,它在逻辑上等同于:

     def custom_decorator(handler): if 'callers' not in dir(handler): handler.callers = {} for e in _listify(ofp_event.EventOFPSwitchFeatures): handler.callers[e] = _Caller(_listify(CONFIG_DISPATCHER), e.__module__) return handler 

    (If you captured the values of ofp_event.EventOFPSwitchFeatures and CONFIG_DISPATCHER at the moment the @set_ev_cls(...) was called). (如果在调用@set_ev_cls(...)时捕获了ofp_event.EventOFPSwitchFeaturesCONFIG_DISPATCHER的值)。

  2. The custom_decorator of step 1 is applied to _switch_features_handler as a more traditional unparameterized decorator. 所述custom_decorator步骤1的被施加到_switch_features_handler作为更传统unparameterized装饰器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM