python学习笔记-装饰器

装饰器

装饰器:本质就是为其他函数添加附加功能
原则:
1.不修改被修饰函数的源代码
2.不修改被修饰函数对调用方式

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

高阶函数定义:
1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
3.满足上述条件任意一个,都可称之为高阶函数

例子:函数的参数是一个函数名
import time
def foo():
    time.sleep(3)
    print("hello")

def test(func):

    #print(func) #内存地址
    start_time=time.time()
    func()
    stop_time=time.time()
    print("函数运行时间是%s"%(stop_time-start_time))

test(foo)

 写一个装饰器

例子1.多运行了一次,不合格

import time
def foo():
    time.sleep(3)
    print("hello")

def timer(func):
    #print(func) #内存地址
    start_time=time.time()
    func()
    stop_time=time.time()
    print("函数运行时间是%s"%(stop_time-start_time))
    return func

foo=timer(foo)
foo()

例子:函数嵌套与作用域回顾

def father(name):
    print("form father %s"%name)
    def son():
        print("my father is %s"%name) #先从本层找name变量,没有就从上一层找
    print(locals()) #显示所有局部变量
    son()
father("steven")

装饰器实现

1、装饰器的架子

import time

def timmer(func):  #func=test
    def wrapper():
        #print(func)
        start_time=time.time()
        func()  #就是在运行test()
        stop_time=time.time()
        print("函数运行时间是%s"%(stop_time-start_time))
    return wrapper

@timmer
def test():
    time.sleep(3)
    print("test函数运行完毕")

#test=timmer(test) 返回的是wrapper的地址
test()  #执行的是wrapper()

#@timmer() 就相当于test=timmer(test)

2、有返回值的情况,获取返回值

import time

def timmer(func):  
    def wrapper():

        start_time=time.time()
        res=func()  #就是在运行test()
        stop_time=time.time()
        print("函数运行时间是%s"%(stop_time-start_time))
        return res
    return wrapper

@timmer
def test():
    time.sleep(3)
    print("test函数运行完毕")
    return "test函数的返回值"

res=test()  #执行的是wrapper()
print(res)

3、函数闭包加上参数

import time

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

        start_time=time.time()
        res=func(*args,**kwargs)  #就是在运行test()
        stop_time=time.time()
        print("函数运行时间是%s"%(stop_time-start_time))
        return res
    return wrapper

@timmer
def test(name,age):
    time.sleep(3)
    print("test函数运行完毕,名称%s,年龄%s"%(name,age))
    return "test函数的返回值"

res=test("张三",18)  #执行的是wrapper()
print(res)

4、补充,解压序列

a,b,c=(1,2,3)     #解压序列
>>> a,b,c=(1,2,3)
>>> a
1
>>> b
2
>>> c
3
>>> l=[2,4,2,3,5,7,8,9,5]
>>> l
[2, 4, 2, 3, 5, 7, 8, 9, 5]
>>> a,*_,c=l   # *代表中间所有的,下划线无意义,可以放一个变量名
>>> a
2
>>> c
5
>>> a,*d,c=l  
>>> a
2
>>> d    #表示取中间所有的
[4, 2, 3, 5, 7, 8, 9]
>>> c
5
>>> l
[2, 4, 2, 3, 5, 7, 8, 9, 5]
>>> a,b,*_,c,d
(2, 2, 4, 2, 3, 5, 7, 8, 9, 5, [4, 2, 3, 5, 7, 8, 9])
>>> b
2
View Code
举例,a=1,b=2。把两个值互换
#方法一
>>> a=1
>>> b=2
>>> x=a
>>> a=b
>>> b=x
>>> a,b
(2, 1)
#方法二
>>> f1=1
>>> f2=2
>>> f1,f2=f2,f1
>>> f1,f2
(2, 1)
View Code

装饰器应用

验证功能装饰器
购物网站举例,略
user_dic={"username":None,"login":False}

def auth_func(func):
    def wrapper(*args,**kwargs):
        if user_dic["username"] and user_dic["login"]:
            res=func(*args,**kwargs)  
            return res
        username=input("用户名:").strip()
        passwd=input("密码:").strip()
        if username=='job' and passwd == "123":
            user_dic["username"]=username
            user_dic["login"]=True
            res=func(*args,**kwargs)  
            return res
        else:
            print("用户名或密码错误")
    return wrapper

@auth_func
def index():
    print("欢迎来到京东主页")

@auth_func
def home(name):
    print("欢迎你回家%s"%name)

@auth_func
def shopping_car(name):
    print("%s购物车里有笔,手机,电脑"%name)

index()
home("产品经理")
shopping_car("产品经理")

复杂的例子

#增加了用户

user_list=[{"name":"steve","passwd":"123"},
           {"name":"mark","passwd":"123"},
           {"name":"jobs","passwd":"123"}]
current_dic={"username":None,"login":False}

def auth_func(func):
    def wrapper(*args,**kwargs):
        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("用户名或密码错误")
    return wrapper

@auth_func
def index():
    print("欢迎来到京东主页")

@auth_func
def home(name):
    print("欢迎你回家%s"%name)

@auth_func
def shopping_car(name):
    print("%s购物车里有笔,手机,电脑"%name)

index()
home("产品经理")
shopping_car("产品经理")

带参数装饰器

user_list=[{"name":"steve","passwd":"123"},
           {"name":"mark","passwd":"123"},
           {"name":"jobs","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("ldap认证")
                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
def index():
    print("欢迎来到京东主页")

@auth(auth_type='ldap')
def home(name):
    print("欢迎你回家%s"%name)

@auth(auth_type='haha')
def shopping_car(name):
    print("%s购物车里有笔,手机,电脑"%name)

index()
home("产品经理")
shopping_car("产品经理")