装饰器的本质是一个闭合函数,该闭合函数的自由变量是一个函数,可以使代码的重要性与扩展性大大加强。
通过@后添加装饰器函数
能够接收任何参数的通用参数装饰器
# def checkParams(fn):
# """只接受字符串的装饰器"""
# def wrapper(strname):
# if isinstance(strname,(str)):#判断是否是字符串类型
# return fn(strname)#如果是则调用fn(strname),返回计算结果
# print("Variable strname is not a string type")
# return
# return wrapper#将装饰后的函数返回
def checkParams(fn):
"""能够接收任何参数的通用参数装饰器"""
def wrapper(*arg,**kwargs):#使用字典和元组的解包参数来做形参
if isinstance(arg[0],(str)):#判断第一个参数是否是字符串
return fn(*arg,**kwargs)
return
return wrapper
@checkParams
def wrapperfun(strname):
def recoder(age):
print("姓名:",strname,"年纪:",age)
return recoder
fun=wrapperfun("Anna")#wrapperfun带有参数检查的闭合函数
fun(37)#为age赋值
fun=wrapperfun(546)#当输入参数不合法时,
fun(37)#没有输出显示
可接收参数的通用装饰器
def isadmin(userid):
"""可接收参数的通用装饰器"""
def checkPArams(fn):
def wrapper(*arg,**kwargs):#定义一个检查参数的函数
if userid!='admin':#
print("Operation is prothibited as you are not admin!")
return
if isinstance(arg[0],(str)):#判断是否是字符串
return fn(*arg,**kwargs)
print("variable strname is not a string type")
return
return wrapper#装饰后的函数返回
return checkPArams
@isadmin(userid="admin")
def wrapperfun(strname):
def recoder(age):
print("姓名:",strname,"年纪:",age)
return recoder
@isadmin(userid="user")
def wrapperfun2(strname):
def recoder(age):
print("姓名:",strname,"年纪:",age)
return recoder
fun=wrapperfun("Ana")
fun(20)
fun1=wrapperfun2("as")
# fun1(37)
fun2=wrapperfun2(123)
除了通过@加函数导入装饰器,还可以通过
wrapperfun=isadmin(userid="admin")(wrapperfun)
实现装饰器导入。
组合装饰器
将不同的装饰器使用@符号一行一行的叠堆起来
@isadmin(userid="admin")
@checkParams
装饰器返回函数的名称修复
当函数被装饰完后,对函数的名字属性再赋一次值,将函数的名称恢复过来
# import functools
def isadmin(userid):
def checkParams(fn):
# @functools.wraps(fn)#保证修饰后的函数与原函数的名称一致
def wrapper(*arg,**kwargs):
if userid!="admin":
print("Operation is prohibited as you are not admin!")
return
if isinstance(arg[0],(str)):
return fn(*arg,**kwargs)
print("variable strname is not a string type")
return
wrapper.__name__=fn.__name__#将函数名称属性恢复,或者通过#@functools.wraps(fn)实现
return wrapper
return checkParams
@isadmin(userid="admin")
def wrapperfun3(strname):
def recoder(age):
print("姓名:",strname,"年纪:",age)
return recoder
wrapperfun3=isadmin(userid="admin")(wrapperfun3)
fun=wrapperfun3("Anana")
fun(22)
通过装饰器实现网站爬取中的重试功能
import requests
def retry(attempt): #定义装饰器函数
def decorator(func):
def wrapper(*args,**kw):
att=0
while att<attempt: #按照计数器att的条件来执行循环语句
print(att)
try: #使用try except捕获异常
return func(*args,**kw) #运行请求
except Exception as e:
att+=1 #调整计数器
return wrapper
return decorator
@retry(attempt=3)
def get_response(url):
r=requests.get(url)
return r
URL="http://www.baidu.com"
r=get_response(URL)
print(r)
if (r!=None):
print(r.content.decode("utf-8"))