Python 装饰器

装饰器

什么是装饰器

装饰器指的是定义一个函数,该函数是用来为其他函数添加而外的功能

为何要用装饰器

开放封闭原则

  • 开放:指的是对拓展功能是开放的
  • 封闭:指的是对修改源代码是封闭的

装饰器就是在不修改被装饰器对象源代码以及调用方式的前提下为被装饰器添加新功能

import time
#源代码
def index(x,y):
    time.sleep(3)
    print('index %s %y' %(x,y))
    
#装饰器,统计函数的运行时间
#使用闭包函数,防止装饰器写死
def outter(func):
    def wrapper(*args,**kwargs):
        start = time.time()
        res = func(*args,**kwargs)	#func放的是index()函数的内存地址,res存放的index()函数的返回值,防止该函数有返回值
        stop = time.time()
        print(stop - start)
        return res
    return wrapper
 
f = outter(index) #index放的是index()函数的内存地址,f 放的是wrapper()函数的内存地址
f(111,2222)

# time.time() 是1970年uninx公元年到现在的秒数

语法糖

让你开心的语法

装饰器的定义要放在被装饰器函数的前面

在被装饰器的正上方的单独一行写@装饰器器名字

@outter	#语法糖,相当于该函数home = outter(home)
def home(name):
    time.sleep(2)
    print("welcome %s to home page"%name)
    
home('egon')

叠加多个装饰器的加载顺序

@deco1	#index = deco1(deco2.wrapper的内存地址)
@deco2	#deco2.wrapper的内存地址 = deco2(deco3.wrapper的内存地址)
@deco3	#deco3.wrapper的内存地址 = deco3(index)
def index():
    pass

装饰器补充,伪装和原函数一样

偷梁换柱,把原函数的属性与解释赋值装饰函数,让装饰器伪装和原函数一样

例如:

函数的名字:函数wrapper.__name__ = 原函数.__name__

函数的解释:函数wrapper.__doc__ = 原函数.__doc__

如果自己把原函数的属性一个个加上去要写很多个,所以引用python的functools库中的wraps,会自动把原函数的属性赋值给装饰器@wraps(func)

from functools import wraps

def outter(func):
    @wraps(func) # 自动获取func函数的属性赋值给wrapper函数
    def wrapper(*args,**kwargs):
        res = func(*args,**kwargs)
        return res
    #将原函数的属性赋值给wrapper函数
    #wrapper.__name__ = func.__name__
	#wrapper.__doc__ = fun.__doc__
    return wrapper

@outter
def index(x,y):
    """这个是主页功能"""
    print(x,y)

有参装饰器

模板:在装饰器外在套一层函数

def 有参装饰器(x,y,z):
	def outter(func):
        def wrapper(*args,**kwargs):
            res = func(*args,**kwargs)
            return res
        return wrapper
    return	outter

@有参装饰器(1,y=2,z=3)
def index():
    pass

例子:判断账号密码来源

#装饰器
def auth(db_type):
    def deco(func):
        def wrapper(*args,**kwargs):
            name = input('your name>>>: ').strip()
            pwd = input('your password>>>: ').strip()
            if db_type == 'file':
                if name == 'mzx' and pwd == '123':
                    print('基于文件的验证')
                    res = func(*args,**kwargs)
                    return res
                else:
                    print('user or password error')
            elif db_type == 'mysql':
                print('基于mysql数据库的验证')
            elif db_type == 'ldap':
                print('基于ldap数据库的验证')
            else:
                print('不支持该db_type')
        return wrapper
    return deco



#源代码
#deco = auth(db_type='file')
#@deco	#账号密码的来源是文件
@auth(db_type='file')
def index(x,y):
    print('index->>%s:%s' %(x,y))
    
#deco = auth(db_type='mysql')
#@deco	#账号密码的来源是数据库
@auth(db_type='mysql')
def home(x,y):
    print('home->>%s:%s' %(x,y))

 

posted @ 2021-03-09 15:05  Hp_mzx  阅读(59)  评论(0)    收藏  举报