首页 > 代码库 > 函数3—装饰器

函数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次写入黑名单
 

函数3—装饰器