Python

python 装饰器

2020-04-01  本文已影响0人  周周周__

装饰器是一种面向切片的思想。主要用到的地方就是给函数封装一个方法。我个人用到的地方就是封装日志。
装饰器是函数的闭包:
简单的理解就是在函数中执行函数

1、为了给函数添加新的功能,普通实现。

def A():
  pring("a")
  def B():
    return "b"
  b = B()
  return b
A() 

在上边的两个函数中, 当我们有一个原始函数B,我们想给B封装一个新的功能,比如这个功能就是在执行B的时候打印一下a,上边的这个函数完全实现了这样的方法,但是这样看来是很不优雅的。对于我们多个需要这个功能的函数是不友好的。所以我们有了装饰器。

2、装饰器实现

def check_rank(func):
    def wrapped_function(*args, **kwargs):
        print('我是装饰器方法。。')
        return func(*args, **kwargs)
    return wrapped_function
@check_rank
def A(x):
    print('123', x)
A(a)

执行A(1), 结果:

结果.png
其中,*args, **kwargs是用来接收参数的。这个方法很好理解,将A函数作为参数传给chenk_renk,在里面封装好的函数wrapped_function里面接收参数,并执行A函数。
这个里面就是把需要的功能封装成函数 wrapped_function,在函数中,首先执行了自己的功能,然后返回的是执行需要执行的函数A,并将执行结果进行返回。把这个结果传到外边函数,外边的函数再将wrapped_function的结果进行返回。

其中,我们针对不通的函数,可能有不同的参数需要传递,比如,flask中的路由,我们传递不同的参数,来给函数绑定不同的路由。这个时候我们就得考虑装饰器传参。

3、装饰器传参

我们都知道,flask值将所有的url都放在了urlmap里面,我们这里可以模仿flask的路由匹配(很牵强,不要在意)。将注册过的路由放在了url_map里面。在装饰器中,只有匹配到了路由才能正常执行。
函数的整个过程只是外边又包装了一个闭包,把装饰器的值进行接收。

from functools import wraps  # 这个是一个基本的方法,为了保证我们装饰器还能打印出当前函数的名称,而不是打印出装饰器函数的名称
url_map = ['/app']
def url_re(res):
    def url_decorator(func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            if res in url_map:
                a = func(*args, **kwargs)
            else:
                a = "you are wrong"
            return a
        return wrapped_function
    return url_decorator
@url_re('/app')
def N():
    print("我是函数N")
    return 'sucess'
@url_re('1')
def M():
    print("我是函数M")
    return

n = N()
print(n)
m = M()
print(m)

结果:


结果.png

4、使用场景说明

1、后端接口鉴权
源码举例:这是针对不同用户权限进行限定访问的

def check_rank(func):
    @wraps(func)
    def wrapped_function(*args, **kwargs):
        if current_user.rank == 2:
            return redirect_back('/')
        elif current_user.rank == 1:
            return func(*args, **kwargs)
    return wrapped_function

2、日志实现(伪代码)

def log_db(request):
    def logging_decorator(func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            a = func(*args, **kwargs)
            try:
               id = requests.remote_addr
               time = time.time()
               msg = requests.mag
               with open('./logs.log', 'a') as f:  # 多进程部署加锁
                    f.write(time + id + msg)
            except Exception as e:
                print(e)
            return a
        return wrapped_function
    return logging_decorator

上一篇 下一篇

猜你喜欢

热点阅读