装饰器

装饰器

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

-原则

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)

原文地址:https://www.cnblogs.com/wode110/p/14697587.html