python基础之装饰器

装饰器的本质是一个闭合函数,该闭合函数的自由变量是一个函数,可以使代码的重要性与扩展性大大加强。

通过@后添加装饰器函数

能够接收任何参数的通用参数装饰器

# 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"))

猜你喜欢

转载自blog.csdn.net/zx520113/article/details/83832054