装饰器

1. 什么叫装饰器

  装饰器本质就是函数,为其他函数添加附加功能

  原则:

  1>.不修改被修饰函数的源代码

  2>.不改变修饰函数的调用方式

 

2. 装饰器的知识储备:

  装饰器 = 高阶函数 + 函数嵌套 + 函数闭包

 

3. 高阶函数

  高阶函数定义:

  1)函数接收的参数是一个函数名

  2)函数的返回值是一个函数名

  3)满足上述条件中的任意一个,都可称之为高阶函数

def mvp(func):             #高阶函数1,接收的参数是一个函数名        
    res = func()
    return res

def dpoy():                  #高阶函数2,函数的返回值是一个函数名
    print('mvp和dpoy都属于lebron')
    return fmvp

def fmvp():
    print('当然fmvp也属于lebron')

 

  高阶函数(把函数当做参数传给高阶函数)的应用1:计算函数运行的时间

import time
def timmer(func):
    start_time = time.time()
    func()
    stop_time = time.time()
    print('函数的运行时间为%s' %(stop_time - start_time))

def test():
    time.sleep(2)
    print('来自函数test')

timmer(test)

#总结:我们确实为函数test增加了test运行时间的功能,但是test原来的执行方式是test(),现在我们需要调用高阶函数timmer(test),改变了函数的调用方式

 

  高阶函数(函数的返回值是一个函数名)的应用2:

import time
def timmer(func):
    start_time = time.time()
    func()
    stop_time = time.time()
    print('函数的运行时间为%s' %(stop_time - start_time))
    return func

def test():
    time.sleep(2)
    print('来自函数test')

test = timmer(test)
test()


#总结:我们为函数test增加了test运行时间的功能,也没有改变test函数的执行方式和源代码,但是这种方法使得test函数运行了两次,相当于没有为foo增加任何新功能

 

  高阶函数总结
  1.函数接收的参数是一个函数名
  作用:在不修改函数源代码的前提下,为函数添加新功能,
  不足:会改变函数的调用方式
  2.函数的返回值是一个函数名
  作用:不修改函数的调用方式
  不足:不能添加新功能

 

4. 函数嵌套

def father(name1):
    print('爸爸是%s' %name1)

    def son(name2):
        print('儿子是%s' %name2)

        def grandson(name3):
            print('孙子是%s' %name3)
        grandson('bose')
    son('xueba')

father('sword')

 

 

5. 闭包

  闭包:在一个作用域里放入定义变量,相当于打了一个包。其实就是对作用域的一种说法,在函数嵌套中,因为作用域的不同,内一层的变量不能在外一层使用,就相当于给内一层的变量封包

def father(name):
    print('爸爸是%s' %name)

    def son():
        name = 'xueba'
        print('儿子是%s' %name)
        def grandson():
            name = 'bose'
            print('孙子是%s' %name)
        grandson()
    son()

father('sword')

 

 

 

6. 无参装饰器

  无参装饰器=高级函数+函数嵌套

  基本框架

def timmer(func):
     def wrapper():  
         res = func()
    return wrapper    

 

  加上参数

def timmer(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
    return wrapper

 

  加上功能

import time

def timmer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        func()
        stop_time = time.time()
        print('函数%s,运行时间%s' %(func, stop_time - start_time)
    return wrapper

  加上返回值

import time
 8
de3f timmer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func()
        stop_time = time.time()
        print('函数%s,运行时间%s' %(func, stop_time - start_time)
        return res
    return wrapper

 

   使用装饰器

import time
def timmer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        stop_time = time.time()
        print('函数的运行时间为%s' %(stop_time - start_time))
        return res
    return wrapper

def test():
    time.sleep(2)
    print('来自函数test')

test = timmer(test)
test()

  语法糖@

import time
def timmer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        stop_time = time.time()
        print('函数的运行时间为%s' %(stop_time - start_time))
        return res
    return wrapper

@timmer     #相当于test = timmer(test)
def test():
    time.sleep(2)
    print('来自函数test')

# test = timmer(test)
test()

 

 

7. 装饰器应用示例

user_list = [
    {'name': 'chen', 'passwd': '123'},
    {'name': 'lebron', 'passwd': '123'},
    {'name': 'druant', 'passwd': '123'},
    {'name': 'curry', 'passwd': '123'}
             ]
user_dic = {'name': None, 'login': False}

def passwd(func):
    def wrapper(*args, **kwargs):
        if user_dic['name'] and user_dic['login']:
            res = func(*args, **kwargs)
            return res
        name = input('用户名:')
        password = input('密码:')
        for index, user_id in enumerate(user_list):
            if name == user_id['name'] and password == user_id['passwd']:
                user_dic['name'] = name
                user_dic['login'] = True
                res = func(*args, **kwargs)
                return res
        else:
            print('用户名或者密码错误')
    return wrapper

@passwd
def home():
    print('欢迎登陆')

@passwd
def ordr():
    print('所有订单')

@passwd
def shopcar():
    print('购物车')

home()

 

 

user_list = [
    {'name': 'chen', 'passwd': '123'},
    {'name': 'lebron', 'passwd': '123'},
    {'name': 'druant', 'passwd': '123'},
    {'name': 'curry', 'passwd': '123'}
             ]
user_dic = {'name': None, 'login': False}

def passwd(passwd_tpye = 'file'):
    def passwd_deo(func):
        def wrapper(*args, **kwargs):
            if passwd_tpye == 'file':
                if user_dic['name'] and user_dic['login']:
                    res = func(*args, **kwargs)
                    return res
                name = input('用户名:')
                password = input('密码:')
                for index, user_id in enumerate(user_list):
                    if name == user_id['name'] and password == user_id['passwd']:
                        user_dic['name'] = name
                        user_dic['login'] = True
                        res = func(*args, **kwargs)
                        return res
                else:
                    print('用户名或者密码错误')
            elif passwd_tpye == 'ldap':
                print('下次再处理')
                res = func(*args, **kwargs)
                return res
        return wrapper
    return passwd_deo
@passwd(passwd_tpye = 'file')     
def home():
    print('欢迎登陆')

@passwd(passwd_tpye = 'ldap')
def ordr():
    print('所有订单')

@passwd(passwd_tpye = 'file')
def shopcar():
    print('购物车')


home()
ordr()

#passwd(passwd_type='file')就是在运行一个函数,然后返回passwd_deco,所以@passwd(passwd_type='file')
就相当于@passwd_deco,只不过现在,我们的passwd_deco作为一个闭包的应用,外层的包passwd给它留了一个passwd_type='file'参数
 

 

    

 

posted @ 2019-03-06 11:05  sword23  阅读(280)  评论(0编辑  收藏  举报