通俗理解装饰器

Python里的装饰器有时候是很好用的,可以减少代码量,比如在django的视图函数中,如果某个函数必须要登录才能访问,那么就以写一个装饰器来装饰那些函数,

首先说一下如何理解装饰器呢,其实很简单,

1.装饰器是一个函数,用来修饰被装饰的函数,使之增加一些额外功能;

2.装饰器有两种调用方式:@decorator   和  @decorator(自定参数列表)

    对于@decorator调用方式Python解释器会自动传入被装饰的函数的函数对象作为装饰器函数的第一个参数,返回一个函数作为被装饰函数的最终执行函数(替代了被装饰函数);

    而 “@decorator(自定参数列表)” 调用方式就相当于函数正常函数调用,但是此时装饰器函数必须返回一个装饰器(函数),接着Python解释器会自动将返回的这个装饰器以@decorator的方式装饰原先的函数,然后返回一个函数作为被装饰函数的最终执行函数(替代了被装饰函数)。

    注意以@decorator方式调用装饰器函数是一定只会传入被装饰的函数对象,没有其他参数。

直接看一个例子(不用理会例子代码的含义,只看形式即可):

'''必须登录的装饰器'''
def required_login(f=None,redirect_url='login',ret_func=None,parameters=()):
    
    if f is None:# @required_login(*args)方式调用,返回一个装饰器函数
        def decorator(view_func):#被返回装饰器
            @wraps(view_func)
            def wrapper(request,*args,**kwargs):
                if request.user.is_authenticated:
                    return view_func(request,*args,**kwargs)
                else:
                    if ret_func is None:
                        return redirect(redirect_url)
                    else:
                        return ret_func(*parameters)
            return wrapper
        return decorator
    else:# @required_login方式调用,返回一个函数对象,这个函数替代了被装饰的函数
        @wraps(f)
        def f1(request,*args,**kwargs):
            if request.user.is_authenticated:
                return f(request,*args,**kwargs)
            else:
                return redirect(redirect_url)
        return f1

@required_login # 第一种调用方式
def test(a):
    print(a)

执行 test('123')相当于:
ret_func=required_login(test)
ret_func('123')


@required_login(redirect_url='login') # 第二种调用方式
def test01(a):
    print(a)

执行test01('123')相当于:
ret_decorator=required_login(redirect_url='login')
ret_func=ret_decorator(test01)
ret_func('123')


这里说明一下@wraps(f)的作用,因为被装饰器装饰的函数在被使用的时候拿到的已经不是原本的函数了,而是装饰器返回的函数对象,也就意味着原函数的信息丢失了,为了解决这个问题可以使用functools 下的 wraps方法 装饰一下 装饰器函数返回的单数,也就是上面看到的,此时装饰器返回的函数对象的信息就变为原函数的信息。

在写代码时不妨这样考虑,要写的装饰器要不要自定义参数,如果不要则装饰器返回一个函数;如果要,则装饰器返回一个装饰器,那么就需要在装饰器函数里写一个被返回的装饰器,这个装饰器同样遵守以上原则。

扫描二维码关注公众号,回复: 5702654 查看本文章

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

猜你喜欢

转载自blog.csdn.net/a1053904672/article/details/88760309