装饰器的使用场景

装饰器常用于:插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计

1、类型检查

不同函数的参数可能会不同,有可能是list,也有可能是dict,所以要对所有函数进行参数检查的话,可以直接加上装饰器来完成

from functools import wraps

def require_ints(func):
    @wraps(func)  # 将func的信息复制给inner
    def inner(*args, **kwargs):
        for arg list(args) + list(kwargs.values()):
            if not isinstance(arg, int:
                raise TypeError("{} 只接受int类型参数".format(func.__name__)
        return func(*args, **kwargs)
    return inner

比如:galaxy中对视图函数的返回值进行校验,将返回数据序列化json数据)

def response_format(func):
    """
    return jsonify format
    """
    @wraps(func)
    def wrappers(*args, **kwargs):
        if not args and not kwargs:
            ret = jsonify(func())
        else:
            ret = jsonify(func(*args, **kwargs))
        return ret
    return wrappers
1.1、@wraps装饰器是什么,有什么样的作用?

原因在使用装饰器装饰函数以后,被装饰的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),当同一装饰器需要装饰多个函数时,会导致被修饰的函数全部变为同一个函数名,运行代码必然会报错。为了不影响,python中的functools包中提供了一个叫wraps的decorator来消除这样的副作用,使用@wraps后,被装饰的函数函数名保持不变。

1.2、Galaxy使用的是flask中的jsonify来序列化数据,为什么不使用python自带的json库中的dumps方法呢

jsonify是Flask封装的扩展包,json.dumps是python系统自带的json模块

  1. jsonify:
    在使用 Flask 写一个接口的时候,需要给客户端返回 JSON 数据,在 Flask 中可以直接使用 jsonify 生成一个 JSON 的响应,并且设置响应的Content-Type为application/json,构造出响应返回至客户端
  2. json.dumps用:
    Content-Type为text/html

Content-Type决定了接收数据的一方如何看待数据,如何处理数据,如果是application/json,则可以直接当做json对象处理,若是text/html,则还要将文本对象转化为json对象再做处理

2、实现单例设计模式

单例模式是一种常用的设计模式,用来确保某一个类只有一个实例存在

def singleton(cls, *args, **kw):
    instances = {
     }
    def _singleton():
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]
    return _singleton

使用单例模式的理由:

比如:galaxy中的日志类,在程序运行期间,有很多地方都需要打印日志,如果每个地方都创建日志对象实例,就会导致系统中存在多个日志实例对象,严重浪费内存资源,事实上,类似这样的日志类,我们希望在程序运行期间只存在一个实例对象

3、权限校验

def jiaoYan(num):
    def setQuan(func):
        def inner(person):
            if num & person.quan == num:    # 当校验通过 可以执行该操作
                func(person)
            else:
                print(person.name, "无权限")
        return inner
    return setQuan

@jiaoYan(1)
def read(person):
    print(person.name, "读代码")

@jiaoYan(2)
def write(person):
    print(person.name, "写代码")

@jiaoYan(4)
def run(person):
    print(person.name, "执行代码")

p1 = Person("张三", 1)    # 只有读权限
p2 = Person("李四", 3)    # 读写权限
p3 = Person("王五", 6)    # 写与执行权限
read(p1)
write(p2)
read(p3)
run(p3)

执行结果为:

张三 读代码
李四 写代码
王五 无权限
王五 执行代码

你可能感兴趣的:(装饰器的使用场景)