什么是装饰器?

装饰器就是用来装饰函数。

  • 想要增强原有函数的功能
  • 但不希望修改原有函数的定义
  • 在代码运行期间动态增加功能的方式

函数嵌套函数

调用方式:
原函数 = 外层函数(原函数名)
原函数

def desc(fun):
    def add_info():
        print('happy today')
        fun()
        print('westos_linux')
    return add_info
def login():
    print('login..')

login = desc(login)
login()

图片描述

def add_info(fun):
    print('happy today')
    fun()
    print('westos_linux')
def login():
    print('login..')
def logout():
    print('logout..')
def save():
    print('save..')
def trans():
    print('trans')

add_info(login)
add_info(logout)
login = add_info(login)

图片描述

装饰器使用

定义的装饰器实质是返回函数的高阶函数
@timeIt(装饰器名) 这里是 python 提供的一个语法糖
1.解决问题:函数执行前后添加功能-->会改变函数调用命令
2.不改变原有函数的调用方式-->函数里面嵌套函数,并且不改变返回嵌套函数的调用方式-->login = desc(login)

计时装饰器

需求:获取每个函数的执行时间
#1.函数执行之前计算时间
#2.函数执行之后计算时间

import random
import string
import time
from functools import reduce

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

def timeit(fun):
    def wrapper(*args,**kwargs):
        t1=time.time()
        res = fun(*args,**kwargs)
        t2 = time.time()
        grot = t2-t1
        print("所需时间:%.6f" %grot)

        return res
    return wrapper

@timeit
def myjoin(*args,**kwargs):
    s = ','.join(*args,**kwargs)
    print(s)

myjoin(li)

图片描述

日志装饰器

#创建装饰器
#1.创建add_log装饰器,被装饰函数打印日志信息
#2.日志格式为:[字符串时间] 函数名:XXX 运行时间:XXXX 运行返回值结果:XXXX
import time
import functools
import math
def add_log(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        run_time =time.ctime()
        start_time  = time.time()
        res = fun(*args,**kwargs)
        end_time = time.time()
        na = fun.__name__
        print('[字符串时间:%s] 函数名:%s 运行时间:%.6f 运行返回值结果:%s' %(run_time,na,end_time-start_time,res))
        return res
    return wrapper

@add_log
def mymult(x,y):
    """这是一个求x的y次方的函数"""
    return math.pow(x,y)
mymult(2,3)

图片描述

登陆验证

#用户登录验证的装饰器is_login
#   如果用户登陆成功,则执行被装饰的函数
#   如果用户登陆不成功,则执行登陆函数


users =['root','sheen']
def is_login(fun):
    def wrapper(*args,**kwargs):
        if kwargs.get('name') in users:
            res  = fun(*args,**kwargs)
        else:
            res = login()
        return res
    return wrapper

@is_login
def writeblog(name):
    return "wirte,now.."

def login():
    return 'please login..'

print(writeblog(name='star'))

图片描述

类型判断(无参)

#1.基础版(无参数)
#编写装饰器required_ints
#   确保函数收到的每一个参数都是整数
#   如果参数不是整形数,打印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')
                break
        else:
            res = fun(*args,**kwargs)
            return res

    return wrapper

@required_ints
def myadd(a,b):
    return a+b

print(myadd(1,2.0))

图片描述

含参类型判断

# #带参数的装饰器
# """
# 装饰器为required_types
#     当装饰器为@required_types(int,float),确保函数接收到的每一个参数都是int/float类型
#     当装饰器为@required_types(list),确保函数接收到的每一个参数都是list类型
#     当装饰器为@required_types(str,int),确保函数接收到的每一个参数都是str/int类型
#     如果参数不满足条件,打印TypeError,参数必须是XXXXX类型
import functools
def required_types(*kinds): #kinds元组
    def required_ints(fun):
        @functools.wraps(fun)
        def wrapper(*args,**kwargs):
            for i in args:
                if  not isinstance(i,kinds):
                    print('TypeError,参数类型为',kinds)
                    break
            else:
                res = fun(*args,**kwargs)
                return res

        return wrapper
    return required_ints

@required_types(int,str)
def my(a,b):
    return a,b
print(my(1,'sdhs'))

图片描述

带有多个装饰器

def makebold(fun):
    print("makebold")
    def wrapper1(*args,**kwargs):
        print("bold")
        return fun(*args,**kwargs)
    return wrapper1

def makei(fun):
    print("makei")
    def wrapper(*args,**kwargs):
        print("i")

        return fun(*args, **kwargs)
    return wrapper  #wrapper=login

#当有多个装饰器时,从下到上调用装饰器
#真实wrapper内容是从上到下执行的
@makebold   #login = makebold(login)    #login为wrapper1
@makei      #login = makei(login)       #login为wrapper
def login():
    return "登陆"

print(login())

图片描述


SheenStar
168 声望26 粉丝

祝你坚强