• 装饰器


    装饰器

    -定义:本质是函数,功能是为其他函数添加附加功能

    -原则

    1,不修改被修饰函数的源代码

    2,不修改被修饰函数的调用方式

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

    高阶函数的定义:

    -函数接收的参数是函数名

    import time
    def foo():
    time.sleep(0.1)
    print('你们好啊')

    def test(func):
    start_time = time.time()
    func()
    end_time = time.time()
    print('运行时间是:%s'%(end_time-start_time))
    test(foo)=======================》此函数接收大参数是函数名,但函数foo()的运行方式改变成了test(foo)
    结果是:你们好啊
    运行时间是:0.10401010513305664

    -函数的返回值也是函数名

    import time
    def foo():
    time.sleep(0.1)
    print('你们好啊')

    def test(func):
    start_time = time.time()
    func()
    end_time = time.time()
    print('运行时间是:%s'%(end_time-start_time))
    return func

    foo = test(foo)======>结果是 你们好啊
    运行时间是:0.10253691673278809
    foo()============>结果是:你们好啊

    满足上述任意一个条件都是高阶函数

    -函数嵌套

    在函数中重新定义一个函数,如下:

    def foo():
    print('你好')
    def test():
    print('alisa')
    test()
    ps:函数也是一个变量

    - 闭包类似于作用域

    装饰器框架(如下):

    def timmer(func):
    def wrapper():
    print(func)
    func()
    return wrapper

    需要计算以下函数运行的时间,写代码(用装饰器):

    import time

    def timmer(func):
    def wrapper():
    start_time = time.time()
    func()
    end_time = time.time()
    print('程序运行时间是%s'%(end_time-start_time))
    return wrapper

    def test():
    time.sleep(0.3)
    print('到此结束')

    test = timmer(test)======》此处timmer(test)运行的结果是返回wrapper的地址
    test()=======》此处相当于运行wrapper()

    注意:上述倒数第二行代码中test = timmer(test)可以换成@timmer 进行简化

    可以直接在需要装饰的函数前写上 @装饰器 直接对函数进行装饰

    -需要装饰的函数添加返回值

    import time
    def timmer(func):
    def wrapper():
    start_time = time.time()
    res = func()
    end_time = time.time()
    print('程序运行时间是%s'%(end_time-start_time))
    return res
    return wrapper

    @timmer
    def test():
    time.sleep(0.3)
    print('到此结束')
    return 'ni'
    res =test()
    print(res)

    运行结果是:

    到此结束
    程序运行时间是0.3040931224822998
    ni

    - 需要装饰的函数加上多个参数

    import time

    def timmer(func):
    def wrapper(*args,**kwargs): ======>注意:*args:上传的是以()元祖的形式,例如:(1,2,3,4)**kargs 上传的是字典的形式 如:(name = alisa)
    start_time = time.time()
    res = func(*args,**kwargs)
    end_time = time.time()
    print('程序运行时间是%s'%(end_time-start_time))
    return res
    return wrapper

    @timmer
    def test(age,name):
    time.sleep(0.3)
    print('到此结束','年龄是【%s】,名字是【%s】'%(age,name))
    return 'ni'
    test(12,'lisa')

    ps: 补充技巧 如下:

    ni = [21,23,22,33,44,55,88,55]

    求第一位元素
    a,*_d =ni=====》a代表第一位元素,d代表最后一位元素 *代表中间元素,_代表不显示
    print(a)======>第一位元素是 21

    求第一位和最后一位元素
    a,*_,d=ni
    print(a,d)====》21,55
    将a = 1 b = 2 变成 a = 2,b = 1 
    a,b=2,1
    print(a,b)====结果是2,1
    
    

    装饰器实例:

    给京东的以下程序添加上验证(用户)功能:

    def index():
    print("欢迎来到京东")
    def home(name):
    print("欢迎回家%s"%name)
    def home(name):
    print("欢迎回家%s"%name)

    首先代码如下:(ps此代码每次进入程序都要验证用户,不方便需改进)def new_fun(func    def wrapper(*args,**kwargs):

            username = input('账户名').strip()
    password = input('密码').strip()
    if username == 'alex' and password == '123':
    res = func(*args,**kwargs)
    return res
    else:
    print('账户或者密码错误')
    return wrapper

    @new_fun
    def index():
    print("欢迎来到京东")

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

    @new_fun
    def shopping_car(name):
    print('%s的购物车里有%s,%s,%s'%('alisa','苹果','橘子','香蕉'))

    index()========》运行结果是:
    账户名alex
    密码123
    欢迎来到京东


    home('产品经理')========》运行结果是:
    账户名alex
    密码123
    欢迎回家产品经理


    shopping_car('产品经理')========》运行结果是:
    账户名alex
    密码123
    alisa的购物车里有苹果,橘子,香蕉

    其次改进后代码如下(不需要每次都验证只需验证一次,就会记住):user_dic ={'username':None,'login':False}def new_fun(func):

        def wrapper(*args,**kwargs):
    if user_dic['username'] and user_dic['login']: # 此处代码是判断用户是否已存在,如果存在的话会直接运行以下程序
    res = func(*args, **kwargs)
    return res
    username = input('账户名').strip()
    password = input('密码').strip()
    if username == 'alex' and password == '123':
    user_dic['username']= username #此处代码是保存客户已登陆的状态
    user_dic['login']= True
    res = func(*args,**kwargs)
    return res
    else:
    print('账户或者密码错误')
    return wrapper

    @new_fun
    def index():
    print("欢迎来到京东")

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

    @new_fun
    def shopping_car(name):
    print('%s的购物车里有%s,%s,%s'%('alisa','苹果','橘子','香蕉'))

    index()=====结果如下:
    账户名alex
    密码123
    欢迎来到京东
    home('产品经理')=====》结果是:欢迎回家产品经理
    shopping_car('产品经理')====〉结果是:alisa的购物车里有苹果,橘子,香蕉

    最后 已有用户列表如下:

    user_list = [{'name':'alex','password':'123'},
    {'name': 'linhaifeng', 'password': '123'},
    {'name': 'wupeiqi', 'password': '123'},
    {'name': 'yuanhao', 'password': '123'},]
    代码如下:
    user_list = [{'name':'alex','password':'123'},
    {'name': 'linhaifeng', 'password': '123'},
    {'name': 'wupeiqi', 'password': '123'},
    {'name': 'yuanhao', 'password': '123'},]
    user_dic ={'username':None,'login':False}
    def new_fun(func):
    def wrapper(*args,**kwargs):
    if user_dic['username'] and user_dic['login']:
    res = func(*args, **kwargs)
    return res
    username = input('账户名').strip()
    password = input('密码').strip()
    for i in user_list: ============》此处运用for循环判断输入的账户名和密码是否在列表user_list内
    if username == i['name'] and password == i['password']:
    user_dic['username']= username====》保存登陆状态
    user_dic['login']= True =======〉保存登陆状态
    res = func(*args,**kwargs)
    return res
    else:============================》else 与for 连在一起(同一个位置):代表整个for 循环运行完毕没有找到,才会显示错误
    print('账户或者密码错误')
    return wrapper

    @new_fun
    def index():
    print("欢迎来到京东")

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

    @new_fun
    def shopping_car(name):
    print('%s的购物车里有%s,%s,%s'%('alisa','苹果','橘子','香蕉'))
    index()
    home('产品经理')
    shopping_car('产品经理')

    随意输入列表内任意name 和password 都可运行程序

     ***************************************************************

    写程序功能

    import os   #引用os模块
    def find(data):=======================》查询功能
    print('这是查询功能')
    print('用户数据是:',data)
    backend_data = 'backend %s'%data
    with open('haproxy.conf','r') as read_f:
    tag = False
    find_list = []
    for readline in read_f:
    if readline.strip() == backend_data: #readline 后边加strip 是因为文章每行后都有空格换行,需要去除空格换行 strip 是去除首位空格换行.
    tag = True
    continue
    if tag and readline.startswith('backend'): #此处的tag = True
    break
    if tag : #此处的tag = True
    print('%s'%readline,end = '') # end = '' 代表去除空行
    find_list.append(readline)

    return find_list #返回查询的结果


    def add():
    pass

    def change(data):=========================》修改功能
    # print('这是修改功能')
    # print('请输入修改数据:',data)
    #data[0] 代表的是文件中的一条记录(原记录)
    backend = data[0]['backend'] #例如代表文件中原记录www.oldboy1.org
    backend_data = 'backend %s'%backend
    old_record = '%sserver %s %s weight %s maxconn %s '%(' '*8,data[0]['record']['server'],
    data[0]['record']['server'],
    data[0]['record']['weight'],
    data[0]['record']['maxconn'])
    #注意文章每一行结束都有换行符
    new_record = '%sserver %s %s weight %s maxconn %s ' % (' '*8, data[1]['record']['server'],
    data[1]['record']['server'],
    data[1]['record']['weight'],
    data[1]['record']['maxconn'])

    print('用户想要修改的记录是:',old_record)
    res = find(backend) #res 是运行查找,查找的结果列表
    print('来自change函数==>',res)
    if not res or old_record not in res: #if not res 代表res=[],原记录查找不到 old_record not in res 代表是查找的ercord不存在原文件
    return'你要修改的记录不存在'
    else:
    index = res.index(old_record)
    res[index] =new_record
    res.insert(0,'%s '%backend_data)

    with open('haproxy.conf','r') as read_f,
    open('haproxy_new.conf','w') as write_f:
    tag = False
    has_write = False
    for readline in read_f:
    if readline.strip() == backend_data:
    tag = True
    continue
    if tag and readline.startswith('backend'):
    tag = False

    if not tag:
    write_f.write(readline)
    else: #此处代表tag = true 的情况下
    if not has_write:
    for record in res:
    write_f.write(record)
    has_write = True
    os.rename('haproxy.conf','haproxy.conf_f')
    os.rename('haproxy_new.conf','haproxy.conf')
    os.remove('haproxy.conf_f')



    def delete():
    pass

    # 三引号作用:1,进行多行注释 2,进行多行定义(如左代码)
    if __name__ == '__main__': # python规范:python文件中只写功能代码,执行/测试之前需写上此代码
    message = '''
    1: 查询
    2:添加'
    3:修改'
    4:删除
    5:退出
    '''

    message_dic = {
    '1':find,
    '2':add,
    '3':change,
    '4':delete}

    while True:
    print(message)
    choice = input('请输入你的选项:').strip()
    if not choice : continue #此处代表判断输入内容是空的情况下,会进行下一次循环
    if choice == '5' : break
    data = input('请输入查询内容').strip()
    if choice != '1':
    data = eval(data)
    #eval() 函数 1:是提取数据结构中的数据 2:求eval(x)相当于sum(x)
    res = message_dic[choice](data)
    print('最终结果是:',res)

    程序简化,结藕后,代码如下

    import os   #引用os模块

    def handle_option(backend_data,type = 'find',res = 'None'):
    if type == 'find':
    with open('haproxy.conf','r') as read_f:
    tag = False
    find_list = []
    for readline in read_f:
    if readline.strip() == backend_data: #readline 后边加strip 是因为文章每行后都有空格换行,需要去除空格换行 strip 是去除首位空格换行.
    tag = True
    continue
    if tag and readline.startswith('backend'): #此处的tag = True
    break
    if tag : #此处的tag = True
    print('%s'%readline,end = '') # end = '' 代表去除空行
    find_list.append(readline)

    return find_list #返回查询的结果

    if type == 'change':
    with open('haproxy.conf', 'r') as read_f,
    open('haproxy_new.conf', 'w') as write_f:
    tag = False
    has_write = False
    for readline in read_f:
    if readline.strip() == backend_data:
    tag = True
    continue
    if tag and readline.startswith('backend'):
    tag = False

    if not tag:
    write_f.write(readline)
    else: # 此处代表tag = true 的情况下
    if not has_write:
    for record in res:
    write_f.write(record)
    has_write = True
    os.rename('haproxy.conf', 'haproxy.conf_f')
    os.rename('haproxy_new.conf', 'haproxy.conf')
    os.remove('haproxy.conf_f')


    def find(data):
    print('这是查询功能')
    print('用户数据是:',data)
    backend_data = 'backend %s'%data
    return handle_option(backend_data)

    def add():
    pass

    def change(data):
    # print('这是修改功能')
    # print('请输入修改数据:',data)
    #data[0] 代表的是文件中的一条记录(原记录)
    backend = data[0]['backend'] #例如代表文件中原记录www.oldboy1.org
    backend_data = 'backend %s'%backend
    old_record = '%sserver %s %s weight %s maxconn %s '%(' '*8,data[0]['record']['server'],
    data[0]['record']['server'],
    data[0]['record']['weight'],
    data[0]['record']['maxconn'])
    #注意文章每一行结束都有换行符
    new_record = '%sserver %s %s weight %s maxconn %s ' % (' '*8, data[1]['record']['server'],
    data[1]['record']['server'],
    data[1]['record']['weight'],
    data[1]['record']['maxconn'])

    print('用户想要修改的记录是:',old_record)
    res = find(backend) #res 是运行查找,查找的结果列表
    print('来自change函数==>',res)
    if not res or old_record not in res: #if not res 代表res=[],原记录查找不到 old_record not in res 代表是查找的ercord不存在原文件
    return'你要修改的记录不存在'
    else:
    index = res.index(old_record)
    res[index] =new_record
    res.insert(0,'%s '%backend_data)
    return handle_option(backend_data,type = 'change',res = res)




    def delete():
    pass

    # 三引号作用:1,进行多行注释 2,进行多行定义(如左代码)
    if __name__ == '__main__': # python规范:python文件中只写功能代码,执行/测试之前需写上此代码
    message = '''
    1: 查询
    2:添加'
    3:修改'
    4:删除
    5:退出
    '''

    message_dic = {
    '1':find,
    '2':add,
    '3':change,
    '4':delete}

    while True:
    print(message)
    choice = input('请输入你的选项:').strip()
    if not choice : continue #此处代表判断输入内容是空的情况下,会进行下一次循环
    if choice == '5' : break
    data = input('请输入查询内容').strip()
    if choice != '1':
    data = eval(data)
    #eval() 函数 1:是提取数据结构中的数据 2:求eval(x)相当于sum(x)
    res = message_dic[choice](data)
    print('最终结果是:',res)

  • 相关阅读:
    js触摸屏案例
    Docker
    Docker 镜像加速
    Docker 命令大全
    linux gpasswd
    Docker基础教程
    PHP输出毫秒时间戳
    PHP Variable handling 函数
    Partition Array by Odd and Even
    Median
  • 原文地址:https://www.cnblogs.com/wode110/p/14697587.html
Copyright © 2020-2023  润新知