栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

python 装饰器

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python 装饰器

python 装饰器 decorator 是以函数为参数并返回函数的高阶函数。

正如字面含义,装饰意思即对其他函数进行修饰,限制等等。

装饰器仅仅是语法糖。 没有装饰器,一切照样可以实现,但需要多几行代码。 使用装饰器则可以帮助你编写更简洁的代码。

1. 一个 decorator 例子

如下的代码:delete_database() 是删除数据库的函数,因为是危险的操作,所以要对其进行修饰(/限制),只允许管理员进行这项操作。

user = {'id': 1,'name': 'a_user','role': 'admin'}
 
def delete_database():
    # perform deletion
    print('Database deleted!')
 
def check_permission(func):
    def wrapper():
        if user.get('role') == 'admin':
            return func()
        else:
            raise PermissionError('Not allowed, you are not an admin!')
    return wrapper
 
secure_delete_database = check_permission(delete_database)

check_permission(func) 即是装饰器,如果是管理员,返回函数,允许操作,否则引发异常。

2. 改为常见的使用 @ 的语法
user = {'id': 1,'name': 'a_user','role': 'admin'}

def check_permission(func):
    def wrapper():
        '''Hi, this is wrapper'''
        if user.get('role') == 'admin':
            return func()
        else:
            raise PermissionError('Not allowed, you are not an admin!')
    return wrapper

@check_permission            # 使用 @ 语法!
def delete_database():
    '''Delete the whole database'''
    # perform deletion
    print('Database deleted!')
 
print(delete_database.__name__)
print(delete_database.__doc__)

上面的代码存在一个问题,就是最后两个print 输出的都是 wrapper 函数的信息:

wrapper
Hi, this is wrapper

解决方法就是 decorator 里再加 decorator:

import functools   # 1 导入 package
    
user = {'id': 1,'name': 'a_user','role': 'admin'}

def check_permission(func):
    @functools.wraps(func)  # 2 对 wrapper 加修饰器
    def wrapper():
        '''Hi, this is wrapper'''
        if user.get('role') == 'admin':
            return func()
        else:
            raise PermissionError('Not allowed, you are not an admin!')
    return wrapper

@check_permission
def delete_database():
    '''Delete the whole database'''
    # perform deletion
    print('Database deleted!')
 
print(delete_database.__name__)
print(delete_database.__doc__)

最后两行变为正确的输出:

delete_database
Delete the whole database
3. 装饰带有参数的函数

装饰带有参数的函数写法例子,这种方法不通用,其他函数想要使用此装饰器,也必须一样加参数:

import functools
 
user = {'user_name':'jose123', 'access_level':'admin'}
 
def user_has_permission(func):
    @functools.wraps(func)
    def secure_func(arg):
        """Hi, this is wrapper secure_func!"""
        if user.get('access_level') == 'admin':
            return func(arg)
    return secure_func
 
@user_has_permission  
def my_function(panel):
    '''retrieves admin password'''
    return f'Password for {panel} panel is 1234.'
 
print(my_function("Shipping"))

使用 *args 和 **kwargs 两种可变参数,使用单个星号参数,可以接受任意数量的位置参数,使用双星号,可以接受任意数量的命名参数:

import functools
 
user = {'user_name':'jose123', 'access_level':'admin'}
 
def user_has_permission(func):
    @functools.wraps(func)
    def secure_func(*args, **kwargs):
        """Hi, this is wrapper secure_func!"""
        if user.get('access_level') == 'admin':
            return func(*args, **kwargs)
    return secure_func
 
@user_has_permission  
def my_function(panel):
    '''retrieves admin password'''
    return f'Password for {panel} panel is 1234.'
    
@user_has_permission
def another():
    pass
 
print(my_function("Shipping"))  # Password for Shipping panel is 1234.
print(another())  # None
4. 装饰器带参数,需要定义 3 级函数:
import functools

user = {'user_name':'jose123', 'access_level':'user'}

def user_has_permission(access_level):
    def my_decorator(func):
        @functools.wraps(func)
        def secure_func(panel):
            """Hi, this is wrapper secure_func!"""
            if user.get('access_level') == access_level:
                return func(panel)
        return secure_func
    return my_decorator
 
@user_has_permission('user')  
def my_function(panel):
    '''retrieves admin password'''
    return f'Password for {panel}  panel is 1234.'

print(my_function("Shipping"))
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1004719.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号