闭包和装饰器

闭包本质上是一个函数,其传入参数和返回值也都是函数,闭包函数的返回值函数是对传入函数进行增强后的结果
目的:在不侵入代码的情况下对函数进行增强;函数业务分类,分类关注点
缺点:需要对wrapper显式的调用(函数的显式增强:每次调用前都需要先调用wrapper)
装饰器约等于闭包,只是一种语法糖,本质上和闭包完全一致
@闭包函数的函数名
函数装饰器装饰在某个函数上,在第一次调用这个函数的时候,python的解释器会自动的增强被装饰的函数

故:python装饰器本质上是一个对函数闭包的语法糖,是函数闭包的简单写法
语法糖:没有增加新的功能,只是一种更方便的写法;可以完全的转化为原本菲语法糖的代码
说明:增强时机:第一次调用之前(没调用,则不增强)
增强次数:只增强一次
在这里插入图片描述

def last_wrapper(info: str):  # 最外面一层的wrapper用于传参
    def wrapper_1(fun):
        def improved_fun1(*args, **kwargs):
            result = fun(*args, **kwargs)
            print(result) 
            return fun(*args, **kwargs)           
            
        return improved_fun1
    return wrapper_1

@last_wrapper(info='info')
def fun(a: int, b: int) -> int:
    return a+b

if __name__ == "__main__":
    fun(1, 3)
    
    # all_fun = last_wrapper(info='str')(fun=fun(1, 3))
    # last_fun = last_wrapper(info='str')
    # second_fun = last_fun(fun=fun)
    # result = second_fun(1, 3)
    # print(result)
    

mmdeploy中的装饰器——注册器机制

from typing import Dict, Type, Optional, Union, List, Callable



class Registry:
    def __init__(self):
        self._module_dict: Dict[str, Type] = dict()
    def _register_module(self,
                         module: Type,
                         module_name: Optional[Union[str, List[str]]] = None,
                         force: bool = False) -> None:

        if module_name is None:
            module_name = module.__name__
        if isinstance(module_name, str):
            module_name = [module_name]
        for name in module_name:
            if not force and name in self._module_dict:
                existed_module = self.module_dict[name]
                raise KeyError(f'{name} is already registered in {self.name} '
                               f'at {existed_module.__module__}')
            self._module_dict[name] = module

    def register_module(
            self,
            name: Optional[Union[str, List[str]]] = None,
            force: bool = False,
            module: Optional[Type] = None) -> Union[type, Callable]:

        # use it as a decorator: @x.register_module()
        def _register(module):
            self._register_module(module=module, module_name=name, force=force)
            return module

        return _register

DATASETS = Registry()

@DATASETS.register_module()
class ADE20KDataset:
    def __init__(self) -> None:
        pass
    
    def get_label_ap(self) -> None:
        pass
    
    
ADE20KDataset() # 无需调用,在装饰完成后,就会执行到self._module_dict[name] = module
  • 生成一个Register的对象,对类ADE20KDataset使用register对象的register_module方法进行装饰
  • 无需调用,在装饰完成后,就会在self._module_dict中维护一个从类名到类的一个映射
class A:
    def __init__(self) -> None:
        pass
    
    def __call__(self, fun) :
        print("the call fun")
        fun()
        print("the over")
        
        

@A()
def fun():
    print("the fun")

结果打印为

the call fun
the fun
the over
class A:
    def __init__(self) -> None:
        pass
    
    def __call__(self, fun) :
        print("the call fun")
        def improved_fun(*args, **kwargs):
            fun(*args, **kwargs)
            print("the over")
        return improved_fun
        
        

@A()
def fun():
    print("the fun")
结果为
the call fun

与函数装饰器不同的是,类方法对类的装饰,会执行改方法

def wrapper(fun):
    def improved_fun(*args, **kwargs):
        fun(*args, **kwargs)
    return improved_fun
 
@wrapper
def fun(a: int) -> None:
    print("the fun have been used")
没有结果输出

闭包

在这里插入图片描述
闭包内的函数,在外部函数执行结束后,复制了一份到内部函数自己的闭包里面
闭包形成的前提条件:

  • 有嵌套的内部函数
  • 外部函数里的变量被内部函数使用了
  • 当外部函数执行结束后(greeting执行结束后,变量才复制到闭包属性里,所以值为second),那些变量的值仍然存在,被存在了内部函数的闭包属性.__closure__属性里面(是一个元组类型)
  • 内部嵌套的函数和使用的变量的组合叫做闭包
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值