首页 > 其他分享 >装饰器

装饰器

时间:2023-01-29 16:03:12浏览次数:34  
标签:logit 函数 作用域 func 装饰 def log

参考https://www.runoob.com/w3cnote/python-func-decorators.html
简洁记录一些对我有用的笔记

python的装饰器是通过闭包的方式实现
先理解了第一段代码,函数式实现的闭包,再看文字

特点:
函数内部嵌套函数
函数内部可以引用外部的变量

闭包是有权限访问其他函数作用域的局部变量的一个函数
闭包的本质是连接函数内部与外部的桥梁
闭包是能访问其他函数内部局部变量的(内部)函数

闭包在JS中的解释
变量的作用域属于函数作用域,在函数执行后作用域就会被清理、内存也随之被收回,但是由于闭包是建立在一个函数内部的子函数,由于其可访问上级作用域的原因,即使上级函数执行完,作用域也不会随之销毁,这时的子函数—也就是闭包,便拥有了访问上级作用域中的变量的权限,即使上级函数执行完后,作用域内的值也不会被销毁

由于闭包可以缓存上级作用域,那么就使得函数外部打破了“函数作用域”的束缚,可以访问函数内部的变量。
以平时使用的 AJAX 成功回调为例,这里其实就是个闭包,由于上述的特性,
回调就拥有了整个上级作用域的访问和操作能力,提高了极大的便利。
开发者不用去学钩子函数来操作上级函数作用域内部的变量了

python 函数闭包
内部定义个新的函数,新的函数执行传入的函数,即被包装的函数,在其前后加入一些代码段如日志、异常处理、权限检查
返回新的函数

from functools import wraps
def decorator_name(f):
    @wraps(f) 
    # 修改装饰后的函数名为传进来的函数名,函数信息不变
    # 否则在打印该函数的信息时将会是decorator_name而不是传入的f
    def decorated_f(*args, **kwargs):
        if not can_run: # 访问外部变量
            return "Function will not run"
        return f(*args, **kwargs)
    return decorated_f
 
# 相当于语句func=decorator_name(func)
@decorator_name # 注意这里没有圆括号
def func():
    return("Function is running")
 
can_run = True
print(func())
# Output: Function is running
 
can_run = False
print(func())
# Output: Function will not run

可接收参数的装饰器

from functools import wraps
 
def logit(logfile='out.log'):
    def logging_decorator(func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            log_string = func.__name__ + " was called"
            print(log_string)
            # 打开logfile,并写入内容
            with open(logfile, 'a') as opened_file:
                # 现在将日志打到指定的logfile
                opened_file.write(log_string + '\n')
            return func(*args, **kwargs)
        return wrapped_function
    return logging_decorator
 
@logit() # 注意,这里有个圆括号,表示的是调用,括号里可以填参数,见下面,实际上相当于@logging_decorator
def myfunc1():
    pass
 
myfunc1()
# Output: myfunc1 was called
# 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串
 
@logit(logfile='func2.log')
def myfunc2():
    pass
 
myfunc2()
# Output: myfunc2 was called
# 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串

通过类实现装饰器,更强大

from functools import wraps
 
class logit(object):
    # 初始化
    def __init__(self, logfile='out.log'):
        self.logfile = logfile
    
    # 调用
    def __call__(self, func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            log_string = func.__name__ + " was called"
            print(log_string)
            # 打开logfile并写入
            with open(self.logfile, 'a') as opened_file:
                # 现在将日志打到指定的文件
                opened_file.write(log_string + '\n')
            # 现在,发送一个通知
            self.notify()
            return func(*args, **kwargs)
        return wrapped_function
 
    def notify(self):
        # logit只打日志,不做别的
        pass

使用方法和函数的装饰器一样@logit
相当于执行func = logit(func)

继承logit装饰器,添加邮件发送功能

class email_logit(logit):
    '''
    一个logit的实现版本,可以在函数调用时发送email给管理员
    '''
    def __init__(self, email='[email protected]', *args, **kwargs):
        self.email = email
        super(email_logit, self).__init__(*args, **kwargs)
 
    def notify(self):
        # 发送一封email到self.email
        # 这里没有实现
        pass

标签:logit,函数,作用域,func,装饰,def,log
From: https://www.cnblogs.com/lxzbky/p/17072912.html

相关文章

  • 装饰者模式和代理模式
    代理模式和装饰器模式很像,这里用【到咖啡馆喝咖啡】作例子来讲解。基础实现定义一个咖啡的接口。publicinterfaceCoffee{/***打印当前咖啡里有什么......
  • Python之装饰器
    #装饰器功能说明"""python中的装饰器(decorator)一般采用语法糖的形式,是一种语法格式。比如:@classmethod,@staticmethod,@property,@xxx.setter,@wraps(),@fun......
  • Day16 -闭包和装饰器
    1.闭包介绍和基本语法1.函数产生嵌套(外函数中定义一个内函数)2.内函数使用外函数定的局部变量3.外函数返回内函数的引用(函数名)闭包的介绍我们前面已经学过了......
  • 设计模式-装饰器模式
    装饰器模式:在不改变原有类的基础上,动态增加一些额外功能举例:定义一个简单的人,刚开始只会走路,经过装饰之后,添加一些技能,会骑车...添加装饰类,实现原理构造方法是返回要......
  • 什么是 Python 中的装饰器?
    装饰器是Python中最强大的设计模式之一。装饰器用于向已创建的对象添加新功能,而无需修改其结构。使用装饰器,您可以轻松包装另一个函数以扩展包装的函数行为,并且无需永久修......
  • 装饰器
    目录装饰器简介无参装饰器有参装饰器装饰器模板装饰器语法糖装饰器简介1.概念 在不改变被装饰对象原代码和调用方式的情况下给被装饰的对象添加新的功能2.本质 ......
  • 小满nestjs(第二十二章 nestjs 自定义装饰器)
    在Nestjs中我们使用了大量装饰器decorator,所以Nestjs也允许我们去自定义装饰器。 案例1自定义权限装饰器生成装饰器 nestgd[name]import{SetMetadata}from'@......
  • 小满nestjs(第四章 前置知识装饰器-实现一个GET请求)
    安装依赖npminstallaxios-S定义控制器 ControllerclassController{constructor(){}getList(){}}定义装饰器这时候需要使用装饰器工厂应为装饰器......
  • 小满nestjs(第三章 前置知识装饰器)
    1、什么是装饰器装饰器是一种特殊的类型声明,他可以附加在类,方法,属性,参数上面装饰器写法tips(需要开启一项配置)类装饰器主要是通过@符号添加装饰器他会自动把class的构造函......
  • Python闭包和装饰器的学习
    之前看了不少的帖子,总是看了这篇帖子说的理解了,换篇帖子说的又不理解了,把人弄晕了,究其原因还是因为没有把底层原理理解。这两个概念总是放在一起说,两者之间肯定是有关系的......