打赏

Python基础(18)——函数闭包和装饰器

装饰器

  装饰器本质就是函数,类似迭代器、生成器。装饰器就是修饰其他函数,为其他函数添加附加功能

  功能实现,就是把函数扔到另个函数内部晃荡一圈,自身没改变,但是另个函数的功能在中间的时候实现了。

  原则:1、不修改被修饰函数的源代码  2、不修改被修饰函数的调用方式               添加新功能,原函数该是什么样还是什么样

  开放封闭原则:一旦程序运行了,比如视频网站正在运行,那么想要添加新功能,又不能关站,现在程序源代码是稳定的,就是封闭的不需要改的,如果修改可能会引起连锁问题。那么开放的原则就是用修饰器来添加新功能

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

高阶函数

  一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数。

  1、函数接收的参数是一个函数名     2、函数的返回值是一个函数名  满足任意一个就是高阶函数

  高阶函数满足不了装饰器的功能,因为高阶函数会在中间执行一遍函数,这样的话 函数就等于执行了两遍

函数嵌套

  是在函数中又定义了一个函数,叫函数嵌套

import time

def timmer(func):

    def wiper():
        start=time.time()
        res=func() #如果这个函数需要返回值,那么这个先赋值最后再返回结果就可以了
        stop=time.time()

        print('last time%s'%(stop-start))
        return res
    return wiper #返回的wiper的地址   相当于用wiper替换了进来的函数,进来的函数嵌套在里面,实现了功能


@timmer
def test():
    print('sososso')

    time.sleep(2)
    return '123'
tes1=test()
print(tes1)

闭包内部参数写法是(*args,**kwargs)这样可以接受任意参数,任意函数,其他的用法也相同,通用写法可变长的参数。接受任意参数,走一遍就吐出去

解压序列

l=[1,3,4,5,6,7,8,8,8,756,754,6]
a,*_,c=l          #*代表所有,_下划线就是没想要这个变量,充当个无意义的变量
print(a,c)    

一个很大的序列,只想要其中的头尾两个,那么可以这么赋值

l=[1,3,4,5,6,7,8,8,8,756,754,6]
a,*b,c=l    #b就得到了中间所有值的列表
print(b)

交换赋值  a,b=b,a

练习题

  写个装饰器,要求为每个功能函数前面加装饰器,实现网站用户验证功能

def yanzheng(func):

    def wrapper(*args,**kwargs):
        username=input('用户名:').strip()
        passwd=input('密码:').strip()
        if username=='sb' and passwd=='123456':

            res=func(*args,**kwargs)
            return res
        else:
            print('error')


    return wrapper


@yanzheng
def index():
    print('abdjlfjd')

如果是登录一个网站,验证了用户名和密码,那么后面进入每个页面的时候就不需要总是输入用户名和密码了,怎么保存已经登录的状态,需要给出用户和登录的状态;另外,用户和密码会有一个列表需要遍历寻找匹配的项

user_list=[
    {'name':'alex','passwd':'123'}     #passwd一定是字符串形式的,不然后面的密码是字符串就会报错
]
current_dic={'username':None,'login':False}   #初始状态为None  和False 在后面记得要赋值 记录状态
def yanzheng(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('error')


    return wrapper    #这个return写的时候最好都是函数一起写在一起,不然后面搞不清楚结构


@yanzheng
def index():
    print('abdjlfjd')

@yanzheng
def dejkl():
    print('sososo')
index()
dejkl()

装饰器加参数

如果用户密码多,那么就涉及数据库了。分关系型数据库,还有集中账号管理数据库。因为涉及读取数据的种类特别多,所以读取类型就是装饰器需要加参数,就是在外面再套一层函数,@的时候直接调外面

def auth(filetype='mysql'):

  之前的没参数的装饰器

  return 装饰器名

和装饰器的原理一样,这样每次@的时候就可以加参数选择需要的类型了,用处不多。

 

posted on 2019-07-05 14:27  大有哥  阅读(153)  评论(0)    收藏  举报

导航