zoukankan      html  css  js  c++  java
  • 函数3—装饰器

    1 为什么要用装饰器
    开放封闭原则 :游戏上线后,尽量避免更改源代码和调用方式,但是出于需求必须为代码增加扩展性

    2 什么是装饰器:
    本质是一种函数 ,没有改动函数源代码和调用方式的情况下,给函数增加一种新的功能
    利用了闭包的原理,闭包的作用就是可以在外部调用这个内部闭包函数,不用关心作用域的问题

    3 装饰器的作用原理:将被装饰函数放入装饰器函数内部的一个闭包函数内,再在外部调用闭包函数

    函数嵌套------->闭包---------->装饰器


    #无参装饰器(被装饰函数无参)
    import time
    def timmer(func):
    def wrapper(): # 闭包函数
    start = time.time()
    func() # 闭包函数内调用被装饰函数
    stop = time.time()
    print('run time is %s'%(stop - start))
    return wrapper # 返回闭包函数

    @timmer #index = timmer(index) 装饰器语法
    def index():
    print('welcome to oldboy!')

    index() # 调用的是装饰后的函数 即 装饰器timmer的返回值wrapper 函数

    #无参装饰器(被装饰函数有参数)
    import time
    from functools import wraps
    def timmer(func):
    @wraps(func) #查看函数注释时查看的是被装饰函数的注释信息
    def wrapper(*args,**kwargs):
    '计算运行时间'
    start = time.time()
    abc = func(*args,**kwargs) # my_max(1,2) abc = res = 2
    stop = time.time()
    print('run time is %s'%(stop - start))
    return abc
    return wrapper

    @timmer #my_max = timmer(my_max)
    def my_max(x,y):
    '比较大小'
    print('my_max function')
    res = x if x > y else y
    return res

    #my_max(1,2)
    ggg = my_max(1,2) # ggg = abc = 2
    print('=============>',ggg)
    print(my_max.__doc__) #查看注释信息
    #无参装饰器(用于多个参数不确定的函数的装饰器)
    import time
    def timmer(func):
    def wrapper(*args,**kwargs):
    start = time.time()
    func(*args,**kwargs)
    stop = time.time()
    print('run time is %s'%(stop - start))
    return wrapper
    @timmer
    def home(name):
    time.sleep(2)
    print('welcome to %s home page'%name)

    @timmer
    def auth(name,passwd):
    print(name,passwd)

    @timmer
    def tell():
    print('-----------------')

    home('drogen')
    auth('egon',123)
    tell()

    #有参装饰器
    def auth2(auth_type):
    def auth(func):
    def wrapper(*args,**kwargs):
    if auth_type == 'file':
    name = input('username: ')
    passwd = input('passwd: ')
    if name == 'egon' and passwd == 123:
    print('auth successful')
    func(*args,**kwargs)
    else:
    print('auth error')

    elif auth_type == 'sql':
    print('还不会呢')

    return wrapper
    return auth

    @auth2(auth_type = 'sql') # @auth index= auth(index) 执行了两个函数 auth2 和 auth
    def index():
    print('welcome to index page')

    index() # 相当于执行函数wrapper

    #函数的多个装饰器

    current_login = {'name':None,'login':False}

    import time
    def timmer(func):
    def wrapper():
    start = time.time()
    abc = func()
    stop = time.time()
    print('run time is %s'%(stop - start))
    return abc
    return wrapper

    def auth2(auth_type):
    def auth(func):
    def wrapper(*args,**kwargs):
    if current_login['name'] and current_login['login']:
    func(*args,**kwargs)
    if auth_type == 'file':
    name = input('username: ')
    passwd = input('passwd: ')
    if name == 'egon' and passwd == '123':
    print('auth successful')
    func(*args,**kwargs)
    current_login['name'] = name
    current_login['login'] = True
    else:
    print('auth error')

    elif auth_type == 'sql':
    print('还不会呢')

    return wrapper
    return auth

    @timmer #index= time(index) index= time(wrapper_xia) index= wrapper_shang
    @auth2(auth_type = 'file') #@auth index = auth(index) index = wrapper_xia
    def index():
    print('welcome to index page')

    @auth2('file')
    def home():
    print('hhhhhhhhhhhhhhhhhhhhh')

    index() #index() = warpper_shang(wrapper_xia())
    home()

    装饰器应用
    1、定义无参装饰器,为被装饰函数添加统计运行时间的功能
    import time
    def timer(func):
    def wrapper():
    start = time.time()
    func()
    stop = time.time()
    print('run time is %s'%(stop - start))
    return wrapper

    @timer
    def bbb():
    print('瞎逼逼')
    bbb()

    2、定义有参装饰器,为被装饰函数添加认证功能:用户信息的来源可以是文件也可以是用户管理系统,三次验证失败锁定用户


    black_list = []
    def auth2(auth_type):
    def auth(func):
    def wrapper():
    if auth_type == 'file':
    while True:
    name = input('name :')
    if name == 'q':
    exit()
    passwd = input('password :')
    with open('black_file1', encoding='utf8')as f2:
    y = f2.read()
    if name not in y:
    with open('account info', encoding='utf8')as f1:
    x = eval(f1.read())
    if name in x and passwd == x[name]:
    print('login successful')
    func()
    break
    elif name not in x:
    print('not found')
    else:
    black_list.append(name)
    black_list.count(name)
    if black_list.count(name) > 2:
    with open('black_file1', 'a+', encoding='utf8')as f2:
    f2.write(name)
    print('name locked!')
    break
    print('login error')
    else:
    print('name has locked')
    elif auth_type == 'ldap':
    print('还他妈不会!')
    return wrapper
    return auth


    @auth2(auth_type = 'file')
    def home():
    print('welcome to home page')
    home()


    思路分析
    # 登录验证时,将黑名单里面的信息读出,与用户输入进行匹配
    #将账户信息里面的字典用eval读出,再将用户输入的与字典的键进行匹配

    #登录错误时,将错误的用户名放入列表,计算列表相同元素的个数,超过3次写入黑名单
     
  • 相关阅读:
    linux 终端分屏命令vsp(转)
    ACE消息队列(转)
    iovec结构体定义及使用 (转)
    转: 写给想成为前端工程师的同学们 (from 360前端团队)
    转:苹果企业级开发者账号申请流程
    奇舞团的博客(360前端团队)
    腾讯开源组件
    转:android studio入门合集
    Raid分类说明 (from mongodb权威指南)
    转: linux下的自动对时
  • 原文地址:https://www.cnblogs.com/liuguniang/p/6714756.html
Copyright © 2011-2022 走看看