python的函数装饰器和类装饰器

2021年02月04日 未雨晴空 0评论 1399阅读 1喜欢

装饰器原理

def decorator(func):
    def wrap_function():
        print("函数执行前")
        func()
        print("函数执行后")

    return wrap_function


def operation(x):
   print(x+x)


if __name__=="__main__":
    decorator(operation(1))

从上面的代码可以知道装饰器就是用来修改其他函数的功能的,这也符合python的哲学简单优雅。

函数装饰器

下面通过函数装饰器实现日志记录

函数装饰器不带参数但目标函数带参数

from functools import wraps


def my_logger(func):
    @wraps(func)
    def record(*args, **kwargs):
        print(func.__name__ + "被执行")
        return func(*args, **kwargs)
    return record


@my_logger
def operation(x):
    return x + x

if __name__=="__main__":
    operation(1)
operation被执行

函数装饰器和被装饰函数都带参数

from functools import wraps


def my_logger(logfile="test.log"):
    def decorator(func):
        @wraps(func)
        def record(*args, **kwargs):
            log_string = func.__name__ + "被执行"
            with open(logfile, 'a') as opened_file:
                opened_file.write(log_string + '\n')
            return func(*args, **kwargs)

        return record
    return decorator

@my_logger(logfile="my.log")
def operation(x):
    return x + x

if __name__=="__main__":
    operation(1)

类装饰器

类装饰器的实现,必须实现callinit两个内置函数。在实现类装饰器的时候,使用init()方法来接收被装饰函数,使用call()方法来添加装饰器要实现的功能,并在call()方法中执行和返回被装饰函数。

下面通过类装饰器实现权限判断

类装饰器和被装饰的函数都不带参数

函数 解释
init 接收被装饰函数,而是接收传入参数
call 接收被装饰函数的参数,实现装饰逻辑;
class BasePermissionDecorator(object):
    def __init__(self,func):
        self.func=func

    def __call__(self, *args, **kwargs):
        if self.check_permission():
            print(f'权限通过开始运行函数{self.func.__name__}')
            return self.func(*args,**kwargs)
        else:
            return print('权限未通过!!!')

    def check_permission(self):
        raise NotImplementedError()


class permit_all(BasePermissionDecorator):
    def check_permission(self):
        print("检查权限")
        print("放开所有权限")
        return True

@permit_all
def upload_file():
    print('上传文件')

if __name__=="__main__":
    upload_file()

运行结果如下:

检查权限
放开所有权限
权限通过开始运行函数upload_file
上传文件

类装饰器带参数但被装饰的函数不带参数

函数 解释
init 不接收被装饰函数,而是接收类装饰器的参数
call 接收被装饰函数。实现装饰逻辑,返回被装饰函数
class BasePermissionDecorator(object):
    def __init__(self,permission_name=""):
        self.permission_name=permission_name

    def __call__(self,func,*args,**kwargs):
        if self.check_permission():
            print(f'权限通过开始运行函数{func.__name__}')
            return func
        else:
            return lambda:print('权限未通过!!!')

    def check_permission(self):
        raise NotImplementedError


class permit_all(BasePermissionDecorator):
    def check_permission(self):
        print(f"检查{self.permission_name}权限")
        print(f"放开所有{self.permission_name}权限")
        return True

@permit_all(permission_name="超级管理员")
def upload_file():
    print('上传文件')

if __name__=="__main__":
    upload_file()

当check_permission返回True时返回如下内容:

检查超级管理员权限
放开所有超级管理员权限
权限通过开始运行函数upload_file
上传文件

当check_permission返回False时返回如下内容:

检查超级管理员权限
放开所有超级管理员权限
权限未通过!!!

类装饰器不带参数但被装饰的函数带参数

函数 解释
init 接收被装饰函数
call 接收被装饰函数的参数,实现装饰逻辑,返回执行被装饰函数的执行的结果
class BasePermissionDecorator(object):
    def __init__(self,func):
     self.func=func

    def __call__(self,*args,**kwargs):
        self.role=args[0]
        if self.check_permission():
            print(f'权限通过开始运行函数{self.func.__name__}')
            return self.func(*args,**kwargs)
        else:
            return print('权限未通过!!!')

    def check_permission(self):
        raise NotImplementedError


class permit_all(BasePermissionDecorator):
    def check_permission(self):
        print("检查权限")
        if self.role=="admin":
            print(f"该用户具有{self.role}权限")
            return True
        else:
            return False

@permit_all
def upload_file(role):
    print('上传文件')

if __name__=="__main__":
    upload_file("admin")

运行结果如下:

检查权限
该用户具有admin权限
权限通过开始运行函数upload_file
上传文件

类装饰器带参数和被装饰函数都带参数

函数 解释
init 不接收被装饰函数,接受类装饰器的参数
call 接收被装饰函数的参数以及参数,实现装饰逻辑,返回一个新的函数;
from functools import wraps


class BasePermissionDecorator(object):
    def __init__(self, permit_role):
        self.permit_role = permit_role

    def __call__(self, func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            self.user_role = args[0]
            if self.check_permission():
                print(f'权限通过开始运行函数{func.__name__}')
                return func(*args, **kwargs)
            else:
                print("权限不匹配")

        return wrapper

    def check_permission(self):
        raise NotImplementedError


class permit_all(BasePermissionDecorator):
    def check_permission(self):
        print("检查权限")
        if self.user_role == self.permit_role:
            print(f"该用户具有{self.permit_role}权限")
            return True
        else:
            return False


@permit_all("admin")
def upload_file(user_role):
    print('上传文件')


if __name__ == "__main__":
    upload_file("admin")

执行下面的语句:

if __name__=="__main__":
    upload_file("admin")

运行结果如下:

检查权限
该用户具有admin权限
权限通过开始运行函数upload_file
上传文件

执行下面的语句:

if __name__=="__main__":
    upload_file("admin11")

运行结果如下:

检查权限
权限不匹配

发表评论 取消回复

电子邮件地址不会被公开。

请输入以http或https开头的URL,格式如:https://oneisall.top