初学者python笔记(装饰器后篇:登陆验证)

装饰器有非常强大的功能,可以不修改函数源代码和调用方式,就给函数加上了对应想要的功能,简直就是 修饰函数的利器。 上一篇文章:初学者python笔记(装饰器、高阶函数、闭包)已经非常详细的剖析了装饰器的原理,本篇就来实现就来具体实现一个登陆验证的案例(源码可以直接使用)

修饰带参数的函数:

被修饰的函数参数个数是不固定的,而要修改参数个数就肯定需要修改装饰器和原函数,违反了装饰器的修改原函数源代码的原则。
而基本装饰器本来是不带有参数的,如果调用原函数需要传入参数怎么办?可以如下操作:

#装饰器
import time
def timmer(func):
    def wrap(*args,**kwargs):
        #一个接收列表,一个接收字典,用容器作为参数就可以不限参数个数了
        #相当于:foo('夏洛特玲玲','50','female','拿破仑','卡塔库栗'),
        #args=['夏洛特玲玲','50','female','拿破仑','卡塔库栗'],kwargs={ }
        start_time = time.time()  #给装饰器加的功能
        res = func(*args,**kwargs)  #在装饰器中运行函数,并且用一个变量来接收以返回原函数的返回值
        stop_time = time.time()
        print('函数运行了{}秒'.format(stop_time - start_time))
        return res  #返回原函数的返回值
    return wrap  #函数的返回值是函数,所以为高阶函数

#原函数
@timmer  #语法糖的使用,使原函数即foo函数被装饰。相当于foo = timmer(foo)语句
def foo(name,age,sex,weapen,son):
    time.sleep(3)
    print('test函数运行完毕!\n名字:%s,年龄:%s, 性别:%s,武器:%s,儿子:%s' %(name,age,sex,weapen,son))
    return '这是test的返回值'  #为了实现把原函数的返回值也接收到

#调用被修饰后的原函数
foo('夏洛特玲玲','50','female','拿破仑','卡塔库栗')  #运行原函数,方式不变,满足原则
#可以看到,加了*args和*kargs后就无论多少个参数都能正常运行了

运行结果:
test函数运行完毕!
名字:夏洛特玲玲,年龄:50, 性别:female,武器:拿破仑,儿子:卡塔库栗
函数运行了3.0121726989746094秒

登陆验证的实现


user_list = [   #查询密码的列表,包含所有的账号密码
    {'name':'路飞','passwd':'1111'},  #重点知识:因为你输入的是字符串,
    {'name':'索隆','passwd':'2222'},    #所以你字典的value也必须是字符串格式,不能是数字格式的值
    {'name':'罗','passwd':'3333'},
    {'name':'基德','passwd':'4444'}
]
current_dic = {'username':None ,'login':False}  #记录当前用户登陆状态的字典

#带验证功能的装饰器
def auth_func(func):
    def wrapper(*args, **kwargs):
        if current_dic['username'] and current_dic['login']:
            #如果都为True就执行,即输入过账号密码后就不需要再次输入了
            res = func(*args, **kwargs)  #直接执行,不需要再输入账号密码
            return res
        #否则就输入账号密码
        username = input('用户名:').strip()  #让用户输入登陆信息
        passwd = input('密码:').strip()
        #遍历字典来匹配账号密码是否正确
        for user_dic in user_list:  #user_dic是用来遍历列表中每个字典的变量
            #print(user_dic['name'],user_dic['passwd'])
            if user_dic['name'] == username and user_dic['passwd'] == passwd: #验证账号密码 
                #print(user_dic['name'],user_dic['passwd'])
                #输入正确就记录下登陆状态,用记录状态的字典
                current_dic['username'] = username
                current_dic['login'] = True
                #print(current_dic['login'])
                res = func(*args, **kwargs)  #接收原函数返回值
                return res
                        
        #else跟for成对,表明如果你输入的连用户名都不存在,那就不用遍历了
        else:
            print('用户名或密码错误!!!')
    return wrapper  #如果密码错误就不会有返回值,而是返回wrapper重新再输入

@auth_func
def index():
    print('欢迎来到淘宝主页!')

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

@auth_func
def shopping_car(name):
    print('%s的购物车里有:%s、%s、%s' %(name,'连衣裙','海贼手办','迪迦凹凸曼'))

print('初始用户状态:',current_dic)
index()
print('输入后用户状态:',current_dic)
home('您')  #该函数无论传入什么值都可以,只是给函数内部多一个全局变量
shopping_car('您')

运行结果:
初始用户状态: {‘username’: None, ‘login’: False}
用户名:索隆
密码:2222
欢迎来到淘宝主页!
输入后用户状态: {‘username’: ‘索隆’, ‘login’: True}
欢迎您回家
您的购物车里有:连衣裙、海贼手办、迪迦凹凸曼

以上就是装饰器案例的实现,如果你看了上一篇装饰器原理的文章,本篇案例肯定是可以理解的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章