thtl

导航

装饰器

装饰器---装饰器就是一个函数,是一个用来修饰别的函数的函数

装饰器是由3部分组成的,  高阶函数+函数嵌套+闭包 3部分组成,其实说白了就是 高阶函数+闭包组成 因为函数嵌套其实就是闭包

 

//高阶函数

参数是函数名或者返回值是函数名就叫高阶函数,之前有讲过,自己回去复习

 

//闭包

闭包就是函数嵌套,只不过现在把函数的作用域换个名字改成叫包,闭包就是在每层包里封装的变量,下面举个例子

def father(name)://最外层的包叫 father ,它里面封装的变量是 name 和 son ,函数即变量所以son也是father这层包封装的变量
    print("我是%s" % name)
    def son()://第二层包叫 son ,它封装的变量是 name 和 grandson 
        name = "DJH"
        print("我的爸爸叫%s" % name)
        def grandson()://最里面的包叫 grandson ,里面没有封装啥变量
            print("我的爷爷叫%s" %name)
        grandson()
    son()
    return None

father("djh")

结果
我是djh
我的爸爸叫DJH
我的爷爷叫DJH
//这个就叫函数的嵌套,在函数里面再定义函数,同时也叫闭包

//装饰器真正上阵-----没有参数的装饰器

 

//被修饰的函数没有参数

import time
def test():
    time.sleep(2)
    print('test is passed!')

def timeer(func):
    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()
        print("test函数执行时间为:%s" % str(stop_time-start_time))
        return None
    return wrapper

test = timeer(test)//这样不太完美,因为每次有需要写这个,可以用python提供的语法省去这一步
test()

结果
test is passed!
test函数执行时间为:2.0014126300811768

import time
def timeer(func):
    def wrapper():
        start_time = time.time()
        res = func()
        stop_time = time.time()
        print("test函数执行时间为:%s" % str(stop_time-start_time))
        return res
    return wrapper

@timeer//这一步相当于test = timeer(test),这样就不需要修饰函数时都加这一步了,先在这个@timeer这样写更美观  注意修饰函数必须写在被修饰的函数前面,不然报错
def test():
    time.sleep(2)
    print('test is passed!')
    return "这是test的返回值"
res = test()
print(res)

结果
test is passed!
test函数执行时间为:2.0014126300811768
这是test的返回值//就被修饰函数的返回值这里重点看一下

 

 //被修饰的函数带参数

其实带参数的装饰器是怎么样的呢,因为装饰器是给被修饰的函数添加一个新功能,也就是说添加的一个新功能就写成装饰器就ok,但是这个被修饰的函数是千般万化的,它的参数的个数也各不相同的,那现在你想到了什么?就是在装饰器里加上收集参数呀,下面举例说明:

import time
def timeer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        stop_time = time.time()
        print("test函数执行时间为:%s" % str(stop_time-start_time))
        return res
    return wrapper

@timeer
def test(name,age)://两个参数
    time.sleep(2)
    print('test is passed!','namme:'+name,'age:'+str(age))
    return "这是test的返回值"

@timeer
def test1(name,age,gender)://三个参数
    time.sleep(2)
    print('test1 is passed!','namme:'+name,'age:'+str(age),'gender:'+gender)
    return "这是test1的返回值"

test('djh',18)//这一步其实是调用wrapper()函数,在其内部有个func()函数,因为@timeer<==>test=timeer(test),所以func其实就是test,因为wrapper()函数的参数是
              //收集参数,故args是一个二元组,将其解包再传给func()函数,相当于直接传两个参数给test()函数
test1('djh',18,'male')//这个也一样只不过现在func相当于test1,args相当于三元组,将其解包传给func相当于直接传3个参数给test1

结果
test is passed! namme:djh age:18
test函数执行时间为:2.000821590423584
test1 is passed! namme:djh age:18 gender:male
test函数执行时间为:2.001034736633301

 

//小知识补充,解压序列

my_list=[2,5,1]
a,b,c=my_list
print(a)
print(b)
print(c)

结果
2
5
1

my_list=[1,6,3,76,4,3,2,5,7,8,6]
a,b,*_,c=my_list//*是标识符,标识着后面的那个符号也就是 _ 相当于列表中间的全部元素----一个元组,a第一个,b第二个,c最后一个
print(a,b,c)
print(_)

结果
1 6 6
[3, 76, 4, 3, 2, 5, 7, 8]

 

//来一个验证用户是否登陆的装饰器吧,就是京东那些店,点开一些东西是要验证你是否登陆的

user_dic=(
    {'name':'djh','password':'123'},
    {'name':'DJH','password':'123'},
    {'name':'hhh','password':'123'},
    {'name':'xxx','password':'123'},
    {'name':'bbb','password':'123'}
)
current_dic={"name":None,'password':None}

def code_check(func):
    def wrapper(*args,**kwargs):
        if current_dic['name'] and current_dic['password']:
            res = func(*args,**kwargs)
            return res
        username = str(input('请输入用户名:')).strip()
        password = str(input('请输入密码:')).strip()
        for each in user_dic:
            if username == each['name'] and password == each['password']:
                current_dic['name']=username
                current_dic['password']=password
                res = func(*args,**kwargs)
                return res
        print("用户名或密码错误!")
        return None
    return wrapper

@code_check
def index():
    print("欢迎来到主页")
    return None

@code_check
def shopping_car(name):
    print("%s,欢迎来到购物车!" % name)
    return None

@code_check
def home(name):
    print("%s,欢迎来到购物车!" % name)
    return None

index()
print("before-->",current_dic)
home("大帅哥djh")
print("after-->",current_dic)
shopping_car('handsome boy djh')

 

//装饰器真正上阵-----带参数的装饰器

def decorator(data_type="filedb"):
    def decorator_true(func):
        def wrapper(*args,**kwargs):
            print("使用的数据库是:%s" % data_type)
            if data_type == 'filedb':
                res = func(*args,**kwargs)
                return res
            elif data_type == 'labdb':
                print("会你妈卖批")
                return None
            else:
                print("自己玩蛋去")
                return None
        return wrapper
    return decorator_true

@decorator()//这里我得着重讲一下,对于python的@语法,也就是装饰器的一个语法来说呀,@后面跟的某一个函数的函数名,也就是函数的内存地址,则该函数就是这个被修饰的函数的
//装饰器,而这里是decorator(),这是什么呢?是函数名后面加了个(),意味着这个是必须调用的函数,然后返回值再和@结合,@decorator()<---->@decorator_True这是什么呢?  
//因为decorator()函数的返回值是decorator_true的函数名,也就是返回了一个真真正正的装饰器的内存地址decorator_True的内存地址
def test(name,age):
    print('name is %s,age %s' %(name,age))
    return None

@decorator('labdb')
def test1(name,age,gender):
    print('name is %s.age %s,gender %s' %(name,age,gender))
    return None

test('djh',18)
test1('DJH',18,'male')

结果
使用的数据库是:filedb
name is djh,age 18
使用的数据库是:labdb
会你妈卖批

 

posted on 2018-08-06 00:45  thtl  阅读(75)  评论(0编辑  收藏  举报