关于Python装饰器的一些理解

今天写后台接口的登录逻辑的时候,遇到了对登录状态的处理,用户登录之后服务器返回给用户token,用户每次调用需要登录的API的时候,就可以根据这个token判断用户是否登录,登录是否过期啥子的了。但是每个路由都对token进行一次验证着实太麻烦了,,而我在java中知道有装饰者模式可以解决这个问题,,所以我查了下,发现python的装饰器也可以解决,而且它也是一个非常重要的东西,所以我就学了下,这里把自己目前的理解写出来,做个记录,纪念我充实的一天。。。。。。

准备知识

1.python函数中可以创建函数

对,没错,就是函数中创建函数,理论上可以一直嵌套

def test():
    print("来做个加法叭")
    x=1
    y=2
    def add(a,b):
        return a+b
    print(add(x,y))

test()

结果:
在这里插入图片描述

2.一切皆为对象,函数也是

顾名思义,一切都是对象,函数也是!


def test():
    return "一切都是对象!"

a = test
print(type(a))
print(a())

结果:

我们把函数test()当成对象赋给了a,可以发现,我们执行a时和执行test时,没啥区别。

3.函数可以当成参数

由上面可以知道,一切都可是对象,函数也是,,所以函数也可以当成别的函数的参数啦

def wrap(fun):
    print("嘿嘿,我在fun前面执行")
    print(fun())
    print("嘿嘿,我在fun后面执行")

def my():
    return "我就是一个卑微的被当成参数的函数"

wrap(my)

结果:
在这里插入图片描述

装饰器基本功能

装饰器的功能嘛,就是装饰用的呗,你看,一般的照片不都有个框子把它装起来么,框子上面都有花边撒,花边就是装饰用的。装饰器也是一样的,当你的函数执行之前要处理或者验证啥子事情的时侯,就可以用装饰器来标记啦。
就拿我开头说的,,我的每个API的函数执行之前,我都要知道它有没有收到token,,我要是每个函数前面都写一遍认证的代码,,我可能要疯。。所以只要用上装饰器,就ok啦。

装饰器的实现

结合刚刚的准备知识,我们可以发现把那3点特性结合起来,就可以实现装饰器的功能啦

def decorator(fun):    #接收要装饰的函数
    def wrap():        #在decorator中新建wrap函数,来执行逻辑,进行“装饰”
        print("嘿嘿,我在fun前面执行")
        print(fun())
        print("嘿嘿,我在fun后面执行")
    return wrap        #返回这个定义好的函数

def my():
    return "我就是一个卑微的被当成参数的函数"


a = decorator(my)
a()

结果
在这里插入图片描述
这样,我们就可以说,把my()函数装饰起来了。可是每次都这样写着实麻烦死了。
但是python里有快速的方法实现:@

def decorator(fun):    #接收要装饰的函数
    def wrap():        #在decorator中新建wrap函数,来执行逻辑,进行“装饰”
        print("嘿嘿,我在fun前面执行")
        print(fun())
        print("嘿嘿,我在fun后面执行")
    return wrap        #返回这个定义好的函数


@decorator             #给my函数加上装饰器decorator
def my():
    return "我就是一个卑微的被当成参数的函数"

my()

结果:
在这里插入图片描述
嘿嘿,是不是一样的效果?这样就可以大量的简化我们的代码了。
真是太妙了,简直是妙蛙种子进了米奇妙妙屋——妙到家了。
在这里插入图片描述

扩展

装饰器的蓝本规范

from functools import wraps
def decorator_name(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if not can_run:
            return "Function will not run"
        return f(*args, **kwargs)
    return decorated
 
@decorator_name
def func():
    return("Function is running")
 
can_run = True
print(func())
# Output: Function is running
 
can_run = False
print(func())
# Output: Function will not run

同时它也可以写成类

from functools import wraps


class logit():
    def __init__(self,x):
        print(x)

    def __call__(self,func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            log_string = func.__name__ + " was called"
            print(log_string)
            return func(*args, **kwargs)

        return wrapped_function

@logit("你好")
def a():
    print("AAAAA")

a()

在这里插入图片描述
这里的__call__是python的类的一种特殊方法,和__init__类似,感兴趣的可以查下。它调用类名()的时侯触发。

它可以用来打印日志:

class logit():
    def __init__(self):
        self.count=0

    def __call__(self,func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            self.count+=1
            log_string = func.__name__ + " was called,the count is"
            print(log_string,self.count)
            return func(*args, **kwargs)

        return wrapped_function

@logit()
def a():
    print()

while True:
    a()
    time.sleep(2)

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值