Python装饰器

什么是装饰器?

官方解释:
装饰器是用来管理和调用函数和类的一个可调用对象,也就是说分为函数装饰器和类装饰器;
但是看完之后,我并不能明白装饰器的含义!!所以我在网上进行了查找,觉得下面的这个解释很通俗,引用于

https://m.php.cn/article/424884.html

装饰器就是对被装饰的对象(函数、类)进行重构的,其可以在不改变原来对象的情况下调用对象时执行重构后的行为。
这里也引用作者得python代码:

def decorator(f):
    def wrapper(x,y):
        return x+y
    return wrapper
@decorator
def func(x,y):
    return 1
func(3,4)

我把这句话分为了三层意思进行理解:
1、装饰器:我们的装饰函数;
2、被装饰对象:引用装饰器的函数或类(类的概念现在还没有学到);
3、返回得可调用对象:装饰器得内嵌函数;
4、重构:(对对象进行重构)
原文作者有提到这样一句话,讲的是****装饰器本身接受被装饰的对象,装饰器返回的可调用对象接受被装饰对象的所有参数。

在上面那一段代码中,
装饰器是: decorator
返回的可调用对象是: wrapper
被装饰的对象是 :func

当调用func(3,4)的时候发生了什么?
此时:返回的可调用对象(wrapper)给了func,你也可以理解为现在的func的代码是
def func(x,y)
		return x+y
装饰器的练习

在这里插入图片描述
timeit 是一个函数,它接受一个参数,这个参数必须是函数(或者说可调用对象或者说是被修饰的函数),并且 timeit 的返回结果一定是一个函数。

带参装饰器

参数分为形式参和实参,带参装饰器其实就是说我们的装饰器中的函数是带有参数的,如果我们在调用函数的时候不手动赋值,那么参数就是使用的默认值,如果手动赋值,那么参数的结果就是我们自己的手动赋值;
引入菜鸟教程的例子:
地址:
https://www.runoob.com/w3cnote/python-func-decorators.html

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()
def myfunc1():
    pass
myfunc1()

# Output: myfunc1 was called
# 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串

@logit(logfile='func2.log')
def myfunc2():
    pass
myfunc2()
# Output: myfunc2 was called
# 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串

保留被装饰函数的函数名字和帮助文档信息在装

饰器函数的下面(闭合函数的上面加:@functools.wraps(fun))

import functools
import random
import string
import time
li = [random.choice(string.ascii_letters) for i in range(100)]
print(time.time()) #打印处自1970年到现在一共多少秒
def timeit(fun):
    # @functools.wraps(fun)
    def wrapper(*args,**kwargs): #接收可变参数 和 关键字参数
        """这是一个装饰器timeit"""
        # 在函数执行之前
        start_time = time.time()
        # 执行函数
        res = fun(*args,**kwargs)
        # 在函数执行之后
        end_time = time.time()
        print('运行时间为:%.6f' %(end_time - start_time))
        return res
    return wrapper
@timeit
def con_add():
    """这是一个con_add"""
    s = ''
    for i in li:
        s +=i
    print(s)
con_add()
print(con_add.__name__)
print(con_add.__doc__)

在这里插入图片描述
如果不加@functools.wraps(fun),则显示的是装饰器的信息
在这里插入图片描述

多个装饰器

多个装饰器装饰函数 从上到下去执行的

def decorator_a(fun):
    def inner_a(*args,**kwargs): #接收可变参数和关键字参数
        print('Get in inner_a')
        fun(*args,**kwargs)
    return inner_a

def decorator_b(fun):
    def inner_b(*args,**kwargs):
        print('Get in inner_b')
        fun(*args,**kwargs)
    return inner_b
 #多个装饰器装饰函数 从上到下去执行的
@decorator_a
@decorator_b
def f(x):
    print('Gat in f')
f(1)

在这里插入图片描述

装饰器的应用

多个装饰器的应用场景
会采用多个装饰器先验证是否登陆成功 再验证权限是否足够

import inspect
login_session = ['root','admin','redhat']
import functools
def is_login(fun):
    @functools.wraps(fun)
    def warapper(*args,**kwargs):#('root',)如果有多个可变参数,args会存成元组
        print(args)
        if args[0] in login_session:
            temp = fun(*args,**kwargs)
            return temp
        else:
            print()
            print('Error:%s 没有登陆成功' %(args[0]))
    return warapper
def is_admin(fun):
    @functools.wraps(fun)
    #inspect_res 会返回一个字典
    # key:形参 value:对应的实参
    def wrapper(*args,**kwargs):
        inspect_res = inspect.getcallargs(fun,*args,**kwargs)
        print('inspect的返回值是:%s' %(inspect_res))
        if inspect_res.get('name') == 'root':
            temp = fun(*args,**kwargs)
            return temp
        else:
            print('not root user,no permisson add user')
    return wrapper
@is_login
@is_admin
def adduser(name):
    print('add_user')
adduser('refhat')

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值