Python之装饰器(综合练习)

装饰器

案例1:

创建装饰器,要求如下:

 1. 创建add_log装饰器,被装饰的函数打印日志信息;
 2. 日志格式为: [字符串时间] 函数名: xxx, 运行时间:xxx, 运行返回值结果:xxx

代码:

import time
import functools

# 定义装饰器
def add_log(fun):
    # 保留被装饰函数的函数名和帮助信息文档
    @functools.wraps(fun)
    def inter(*args,**kwargs):
        # time.time():  秒数
        start_time = time.time()
        # 由于被装饰函数有返回值
        res = fun(*args,**kwargs)
        end_time = time.time()
        # 运行返回值结果:即为函数的返回值,fun.__name__:返回函数名
        print('[%s] 函数名:%s, 运行时间:%.6f, 运行返回值结果:%d'
              %(time.ctime(),fun.__name__,end_time - start_time,res))
        # 所以必须return返回函数返回值
        return res
    return inter

# 添加装饰
@add_log
# 定义被装饰函数(求任意两个数的和)
def add(x,y):
    # 休眠1秒
    time.sleep(1)
    return x+y

# 调用函数
print(add(1,10))

# 输出时间; time.ctime():以正常的格式显示时间
# print(time.ctime())

运行结果:
在这里插入图片描述
案例2:

需求:
仅root用户可以有权限执行以下函数,当普通用户执行时会报错

#提示: 如何返回函数的实参?
      inspect.getcallargs(函数名,参数):以字典的形式返回函数的参数 ( {形参:实参} )
      get方法:返回字典指定key的value值

代码:

import functools
import inspect

# 定义装饰器
def is_root(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        # inspect.getcallargs:以字典的形式返回函数的参数
        # key值为:形参,value值为:形参对应的实参
        inspect_res = inspect.getcallargs(fun,*args,**kwargs)
        print('inspect_res的返回值为:%s' % inspect_res)
        # get方法:返回字典指定key的value值
        if inspect_res.get('name') == 'root':
            res = fun(*args,**kwargs)
            return res
        else:
             print('ERROR:you are not a root user')
    return  wrapper

# 添加装饰
@is_root
# 定义被装饰的函数
def add_student(name):
    print('添加学生信息...')

# 调用函数
add_student('westos')

运行结果:
在这里插入图片描述
改进:(需要用到多个装饰器)

先让用户登陆,再判断用户是否由权限执行添加信息功能

代码:

import functools
import inspect

userlist = ['root','admin','student']

# 定义装饰器1(判断用户是否登陆成功)
def user_login(fun):
    @functools.wraps(fun)
    def logins(*args,**kwargs):
        for i in args:
            if i not in userlist:
                print('Error:登陆失败')
            else:
            	print('登陆成功')
                res = fun(*args,**kwargs)
                return res
    return logins

# 定义装饰器2(判断用户是否为root用户)
def is_root(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        # inspect.getcallargs:以字典的形式返回函数的参数
        # key值为:形参,value值为:形参对应的实参
        inspect_res = inspect.getcallargs(fun,*args,**kwargs)
        print('inspect_res的返回值为:%s' % inspect_res)
        # get方法:返回字典指定key的value值
        if inspect_res.get('name') == 'root':
            res = fun(*args,**kwargs)
            return res
        else:
             print('ERROR:you are not a root user')
    return  wrapper

# 添加装饰(装饰器的内部功能函数从上到下依次执行)
@user_login
@is_root
# 定义被装饰的函数
def add_student(name):
    print('添加学生信息...')

# 调用函数
add_student('admin')

运行结果:
在这里插入图片描述
案例3:

编写装饰器required_ints, 条件如下:
    1). 确保函数接收到的每一个参数都是整数;
        # 提示:如何判断变量的类型?
          type(s)             # 输出s的类型
          isinstance(s,str)   # 判断s是否为字符串类型
    2). 如果参数不是整形数,抛出异常: 参数必须为整形;
        # 提示:如何抛出异常?
          raise TypeError(“参数必须为整形”)

代码:

import functools
# 定义装饰器
def required_ints(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        # 遍历整个想要求和的元组
        for i in args + tuple(kwargs.values()):
            # 判断每个元素是否为整型,如果不是,则抛出异常
            if not isinstance(i,int):
                # raise TypeError(): 抛出异常
                raise TypeError('参数必须为整形')
        else:
            # 调用函数,并返回函数返回值
            res = fun(*args,**kwargs)
            return res
    return wrapper
    
# 添加装饰
@required_ints
# 定义被装饰函数:
# *args:可变参数  **kwargs:关键字参数
def add(*args,**kwargs):
    # args:字典类型   kwargs.values():元组类型
    # 由于数据类型不同,所以不能直接用+来连接,必须先转换数据类型
    return sum(args + tuple(kwargs.values()))

# 注意:如果有字典类型的实参,则必须写在最后边
print(add(1,2.0,a=3,b=5))

Python之装饰器(综合练习)_第1张图片

你可能感兴趣的:(Python之装饰器(综合练习))