Python函数装饰器

tengyunjiawucom 2020-02-13

装饰器的原则

1)不修改被修饰函数的源代码;

2)不修改被修饰函数的调用方式;

装饰器的知识点 = 高阶函数 + 函数嵌套 + 闭包

1. 只用高阶函数写装饰器--->有瑕疵

import time

def foo():
    print(‘this is foo‘)
    # return foo

def timer(func):
    starttime = time.time()
    func()
    stoptime = time.time()
    print(‘使用的时间是:%s‘ %(stoptime - starttime))
    return func

foo = timer(foo)
foo()

#执行结果是:
# this is foo
# 使用的时间是:0.00013685226440429688
# this is foo            #多了一次执行结果

2. 闭包其实就是函数的嵌套

def First(name):
    print(‘FirstLayer:%s‘ %name)
    def Second():
        name = ‘bbb‘
        print(‘SecondLayer:%s‘ %name)
        def Third():
            name = ‘ccc‘
            print(‘ThirdLayer:%s‘ %name)
        Third()
    Second()
First(‘aaa‘)

3. 函数闭包装饰器基本实现

# 实现阶段1:只需要在原来函数调用之前进行赋值操作。
import  time

def timer(func):   #func == test
    def good():
        starttime = time.time()
        func()
        stoptime = time.time()
        print(‘程序消耗的时间是:%s‘ %(stoptime - starttime))
    return good

def test():
    print(‘这是test函数‘)

test = timer(test)      #此处函数运行的结果是return的good,可以看下一步证实。
print(timer(test))      #<function timer.<locals>.good at 0x10e3cb700>,因此需要下一步运行返回值函数good。
test()                  #test = good
# 实现阶段2:通过语法糖改进后,完全不需要动原来函数;
import time

def timer(func):   #func == test
    def good():
        starttime = time.time()
        func()
        stoptime = time.time()
        print(‘程序消耗的时间是:%s‘ %(stoptime - starttime))
    return good

@timer  #@timer  相当于 test = timer(test)

def test():
    print(‘这是test函数‘)
test()
# 实现阶段3:如何打印出真正test的返回值
import time

def timer(func):   #func == test
    def good():
        starttime = time.time()
        res = func()            #就是在运行test()
        stoptime = time.time()
        print(‘程序消耗的时间是:%s‘ %(stoptime - starttime))
        return res
    return good

@timer  #@timer  相当于 test = timer(test)

def test():
    print(‘这是test函数‘)
    return ‘这是test的返回值‘
ras = test()
print(ras)
# 阶段4装饰器适用于不同参数个数的函数
import time

def timer(func):   #func == test
    def good(*args,**kwargs):
        starttime = time.time()
        res = func(*args,**kwargs)            #就是在运行test()
        stoptime = time.time()
        print(‘程序消耗的时间是:%s‘ %(stoptime - starttime))
        return res
    return good

@timer  #@timer  相当于 test = timer(test)

def test(name,age,gender):
    print(‘这是test函数,名字是%s,年龄是%s,性别是%s‘ %(name,age,gender))
    return ‘这是test的返回值‘
ras = test(‘aaa‘,‘18‘,‘male‘)
print(ras)

@timer   #@timer  相当于 test1 = timer(test1)
def test1(name,age,gender,hight):
    print(‘这是test1函数,,名字是%s,年龄是%s,性别是%s,身高是%s‘ %(name,age,gender,hight))
    return ‘这是test1的返回值‘
ras = test1(‘bbb‘,‘20‘,‘male‘,‘175‘)
print(ras)

# 如下为返回结果:
# 这是test函数,名字是aaa,年龄是18,性别是male
# 程序消耗的时间是:8.0108642578125e-05
# 这是test的返回值
# 这是test1函数,,名字是bbb,年龄是20,性别是male,身高是175
# 程序消耗的时间是:1.0013580322265625e-05
# 这是test1的返回值

4. 解压序列补充

# 使用解压序列取列表中的最开头和最结尾的值,可灵活使用。
>>> l = [1,2,3,4,5,6]
>>> a,*_,b = l
>>> l
[1, 2, 3, 4, 5, 6]
>>> a
1
>>> b
6
>>> a,*b,c = l
>>> a
1
>>> b
[2, 3, 4, 5]
>>> c
6
#快速交换两个变量的值
>>> f1,f2 = 1,2
>>> f1
1
>>> f2
2
>>> f1,f2 = f2,f1
>>> f1
2
>>> f2
1

5. 终极版装饰器-带参数验证功能的装饰器

user_list=[
    {‘name‘:‘alex‘,‘passwd‘:‘123‘},
    {‘name‘:‘linhaifeng‘,‘passwd‘:‘123‘},
    {‘name‘:‘wupeiqi‘,‘passwd‘:‘123‘},
    {‘name‘:‘yuanhao‘,‘passwd‘:‘123‘},
]
current_dic={‘username‘:None,‘login‘:False}

def auth(auth_type=‘filedb‘):
    def auth_func(func):
        def wrapper(*args,**kwargs):
            print(‘认证类型是‘,auth_type)
            if auth_type == ‘filedb‘:
                if current_dic[‘username‘] and current_dic[‘login‘]:
                    res = func(*args, **kwargs)
                    return res
                username=input(‘用户名:‘).strip()
                passwd=input(‘密码:‘).strip()
                for user_dic in user_list:
                    if username == user_dic[‘name‘] and passwd == user_dic[‘passwd‘]:
                        current_dic[‘username‘]=username
                        current_dic[‘login‘]=True
                        res = func(*args, **kwargs)
                        return res
                else:
                    print(‘用户名或者密码错误‘)
            elif auth_type == ‘ldap‘:
                print(‘鬼才特么会玩‘)
                res = func(*args, **kwargs)
                return res
            else:
                print(‘鬼才知道你用的什么认证方式‘)
                res = func(*args, **kwargs)
                return res

        return wrapper
    return auth_func

@auth(auth_type=‘filedb‘) #auth_func=auth(auth_type=‘filedb‘)-->@auth_func 附加了一个auth_type  --->index=auth_func(index)
def index():
    print(‘欢迎来到京东主页‘)

@auth(auth_type=‘ldap‘)
def home(name):
    print(‘欢迎回家%s‘ %name)
#
@auth(auth_type=‘sssssss‘)
def shopping_car(name):
    print(‘%s的购物车里有[%s,%s,%s]‘ %(name,‘奶茶‘,‘妹妹‘,‘娃娃‘))

# print(‘before-->‘,current_dic)
# index()
# print(‘after--->‘,current_dic)
# home(‘产品经理‘)
shopping_car(‘产品经理‘)

相关推荐