• python装饰器


    python 装饰器

    装饰器的本质是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能。

    装饰器返回值是一个函数;接收参数也是一个函数(参数是我们业务要执行的函数)。

    一个简单示例

    #  定义一个简单的装饰器
    def a_new_decorator(a_func):
        def wrapTheFunction():
            print("before executing a_func()"
            a_func()
            print("after executing a_func()"
        return wrapTheFunction
                  
    def a_function():
    	print('main func')
                
    # 装饰器执行的过程              
    a_function = a_new_decorator(a_function)
    a_function()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    过程:装饰器把要执行的函数作为参数传给自己,在创建一个同名函数对象代替要执行的函数

    使用@

    @a_new_decorator
    def a_function():
    	print('main func')
       
    a_function()
    # 执行效果同上
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    functools.wraps

    functools.wraps保留原函数的名字和注释文档(docstring)

    from functools import wraps
    
    #  定义一个装饰器
    def a_new_decorator(a_func):
        @wraps(a_func)
        def wrapTheFunction():
            print("before executing a_func()"
            a_func()
            print("after executing a_func()"
        return wrapTheFunction
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    函数参数

    参数可以通*args、**kwargs

    from functools import wraps
    def decorator_name(f):
        @wraps(f)
        def decorated(*args, **kwargs):
        	if not can_run:
        		return "Function will not run"
        	return f(*args, **kwargs)
        return decorated
    
    @decorator_name
    def func(msg:str):
        print(msg)
    	return("Function is running")
    
    can_run = True
    print(func("hahah"))
    # Output: hahah
    # Output: Function is running
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    带参数的装饰器

    外层再套一个函数

    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 wrapped_function
        return logging_decorator
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    @logit()
    def myfunc1():
    	pass
    myfunc1()
    # Output: myfunc1 was called
    # 现在⼀个叫做 out.log 的⽂件出现了,⾥⾯的内容就是上⾯的字符串
    @logit(logfile='func2.log')
    def myfunc2():
    	pass
    
    myfunc2()
    # Output: myfunc2 was called
    # 现在⼀个叫做 func2.log 的⽂件出现了,⾥⾯的内容就是上⾯的字符串
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    装饰类

    类也可以用来构建装饰器

    class logit(object):
        def __init__(self,logfile='out.log'):
            self.logfile = logfile
        # __call__ :可以使用类名调用__call__函数的实现
        def __call__(self,func):
            log_string = func.__name__+" was called"
            print(log_string)
            with open(self.logfile,'a') as open_file:
                open_file.write(log_string+"\n")
            self.notify()
            
        def notify(self):
            # 打印日志
            pass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    @logit()
    def func1():
    	pass
    
    • 1
    • 2
    • 3

    可以继承logit,扩展功能

    # 来添加email的功能,保留原来的记录日志的功能
    class email_logit(logit):
        def __init__(self, email='admin@myproject.com', *args, **kwargs)
            self.email = email
            super(logit, self).__init__(*args, **kwargs)
            
        def notify(self):
            # 打印日志
            # send emil 
            pass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    集合的增删改查?--Python
    【linux】基础IO+系统文件IO+文件描述符分配规则
    ant javac任务的fork和executable属性
    vue路由
    浅谈面试Java中线程池解析
    代码随想录——最长递增子序列的个数
    Linux C/C++ UDP Socket 网络通信
    【22-23春】AI作业10-经典卷积网络
    VUE全家桶 (Vue-cli、Vue-route、Vuex)学习笔记
    先验概率 / 后验概率 / 条件概率 / 全概率公式 / 贝叶斯公式
  • 原文地址:https://blog.csdn.net/qq_27953479/article/details/132757290