python3---装饰器

装饰器的定义

把一个函数当作参数,返回一个替代版的函数
本质上就是一个返回函数的函数

在不改变原函数的基础上,给函数增加功能
def outer(func):
   def inner(age):
       if age<0:
           age = 0
       func(age)
   return inner

@outer	   # 语法糖,相当于 say = outer(say)
def say(age):
    print('man is %s years old' %age)

# say = outer(say)
say(-1)

在这里插入图片描述

装饰器的应用

多个函数使用一个装饰器

 def desc(fun):  # 需要传递一个函数,要装饰的函数
    def add_info():  # 装饰器函数里要嵌套函数
        print('元旦快乐~')
        fun()				# 执行装饰函数里面的函数对象
        print('欢迎光临西部开源~')
    return add_info    # 返回值是嵌套的函数对象

@desc   # 如何调用装饰器(两种方式)
def login():
    print('login....')

# login = desc(login)  # 返回值是一个函数
# login()
@desc
def logout():
    print('logout...')

@desc
def savemoney():
    print('存钱...')

@desc
def transfermoney():
    print('转账...')


login()
logout()
savemoney()
transfermoney()

在这里插入图片描述

装饰器实现一个计时器

import time
import string
import random
import functools

li = [random.choice(string.ascii_letters) for i in range(10)]


# 问题1:装饰的函数有返回值
# 问题2:如何保留被装饰函数的函数名和帮助信息文档
def timeit(fun):
    """这是一个装饰器timeit"""

    @functools.wraps(fun)  # 可以保留被装饰函数的函数名和帮助信息文档
    def add_time(*args, **kwargs):  # 接收可变参数和关键字参数
        """这是一个add_time函数"""
        # 在函数执行之前计时
        start_time = time.time()
        # 执行函数
        # 函数有返回值时,将函数赋给res
        res = fun(*args, **kwargs)
        # 在函数执行之后计时
        end_time = time.time()
        print('运行时间:%.6f' % (end_time - start_time))
        # 返回res
        return res

    return add_time


@timeit
def con_add():
    """这是con_add函数,被timeit装饰"""
    s = ''
    for i in li:
        s += i + ','
    print(s)


@timeit
def join_add():
    """这是join_add函数,被timeit装饰"""
    print(','.join(li))


@timeit
def fun_list(n):
    # 函数有返回值
    return (i for i in range(n) if n % 2 == 0)


@timeit
def fun_filter(n):
    return (filter(lambda x: (x % 2 == 0), range(n)))


def func():
    """这是func函数"""
    print('hello')


con_add()
join_add()

print(fun_list(5000))
print(fun_filter(5000))

print(func.__doc__)
print(func.__name__)

print(con_add.__doc__)
print(con_add.__name__)

print(join_add.__doc__)
print(join_add.__name__)

在这里插入图片描述

装饰器实现对用户权限的判断

import functools
import inspect


def is_admin(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        # inspect.getcallargs返回一个字典,key值:形参,value值:对应的实参
        inspect_res = inspect.getcallargs(fun, *args, **kwargs)
        print('inspect的返回值:%s' % inspect_res)
        if inspect_res.get('name') == 'admin':
            res = fun(*args, **kwargs)
            return res
        else:
            print('not admin user,no permisson!')

    return wrapper


@is_admin
def add_student(name):
    print('添加学生信息~')

@is_admin
def del_student(name):
print('删除学生信息~')

add_student('admin')
del_student('student')

在这里插入图片描述

练习_创建装饰器

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

def add_log(fun):
    @functools.wraps(fun)
    def print_Info(*args, **kwargs):
        start_time = time.time()
        res = fun(*args, **kwargs)
        end_time = time.time()
        print('字符串时间:[%s] 函数名:%s 运行时间:%.6f 运行返回值结果:%s'
              %(time.ctime(),fun.__name__,end_time - start_time,res))
        return res

    return print_Info


@add_log
def fun_filter(n):
    time.sleep(1)
    return list(filter(lambda x: (x % 2 == 0), range(n)))

fun_filter(5)

在这里插入图片描述

多个装饰器

有多个装饰器的时候,函数从上到下执行的

def decorator_a(fun):
    print('Get in decorator_a')
    def inner_a(*args,**kwargs):
        print('Get in inner_a')
        return fun(*args,**kwargs)
    return inner_a

def decorator_b(fun):
    print('Get in decorator_b')
    def inner_b(*args,**kwargs):
        print('Get in inner_b')
        return fun(*args,**kwargs)
    return inner_b
    
"""
当有多个装饰器的时候,装饰器decorator是从下到上调用
但真实的inner函数内容是从上到下执行的
"""
@decorator_b
@decorator_a
def f():
    print('Get in f')
    
f()

在这里插入图片描述

应用:用多个装饰器先验证用户是否登陆成功,再验证是否有权限

import functools
import inspect


def is_admin(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        inspect_res = inspect.getcallargs(fun, *args, **kwargs)
        if inspect_res.get('name') == 'admin':
            res = fun(*args, **kwargs)
            return res
        else:
            print('%s not admin user,no permisson!' % args[0])

    return wrapper


login_session = ['admin', 'root', 'westos']


def is_login(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        if args[0] in login_session:
            res = fun(*args, **kwargs)
            return res
        else:
            print('%s not login!' % args[0])

    return wrapper


@is_login
@is_admin
def add_student(name):
    print('添加学生信息~')


add_student('redhat')
add_student('westos')
add_student('admin')

在这里插入图片描述

练习_创建装饰器

编写装饰器required_ints,条件如下:
1.确保函数收到的每一个参数都是整数
2.如果参数不是整型数,打印 TypeError:参数必须为整型
import functools


def required_ints(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        for i in args:
            if not isinstance(i, int):
                print('TypeError:参数必须为整型')
                return
        else:
            res = fun(*args, **kwargs)
            return res

    return wrapper


@required_ints
def add(x, y):
    print(x+y)

add(1, 2)
add(1, 2.5)

在这里插入图片描述

应用:带参数的装饰器

import time
import functools

def log(kind):	# kind = 'debug'
    def add_log(fun):
        @functools.wraps(fun)
        def print_Info(*args, **kwargs):
            start_time = time.time()
            res = fun(*args, **kwargs)
            end_time = time.time()
            print('字符串格式:<%s> 字符串时间:[%s] 函数名:%s 运行时间:%.6f 运行返回值结果:%s'
                  %(kind,time.ctime(),fun.__name__,end_time - start_time,res))
            return res

        return print_Info

    return add_log


@log('debug')
# log('debug') ====> 返回值:add_log
def add(x,y):
    time.sleep(1)
    return x+y

add(5,6)

在这里插入图片描述

练习_创建装饰器

编写装饰器required_types,条件如下:
1.当装饰器为@required_types(int,float)时,确保函数接收到的每一个参数都是int或者float类型;
2.当装饰器为@required_types(list)时,确保函数接收到的每一个参数都是list类型;
3.当装饰器为@required_types(str,int)时,确保函数接收到的每一个参数都是str或者int类型;
4.如果参数不满足条件,打印 TypeError:参数必须为xxxx类型
import functools


def required_types(*kind):
    def required(fun):
        @functools.wraps(fun)
        def wrapper(*args, **kwargs):
            for i in args:
                if not isinstance(i, kind):
                    print('TypeError:参数必须为:',kind)
                    return
            else:
                res = fun(*args, **kwargs)
                return res

        return wrapper

    return required


@required_types(int,float)
def add(x, y):
    print(x , y)


add(1.5,3)
add('westos', 2.5)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值