装饰器在大型项目中几个有趣的用法

前言

众所周知,Python是一门动态语言,变量不需要声明类型,这种灵活的形式让多人进行大型Python开发时会面临类型不明确的问题,项目中类和方法很多了,方法的参数就会让人迷惑,如果开发者自身编码风格又比较随意,那么项目就会变得难以维护。

受公司项目启发,这里分享关于装饰器的几点思考。

“全局”静态方法

静态方法很简单,使用@staticmethod装饰器则可,简单例子如下:

class MyClass(object):
    name = '二两'
    @staticmethod
    def myfun():
        print(f'I love {MyClass.name}')

使用时:

MyClass.myfun()

这种方式会让代码显得直观,此时类就变成了方法集合者,用于表示相同类别的方法。

通常,在一个大型项目中,不同模块会分层处理,比如数据库操作相关的内容放在Modules目录下,数据过滤方面的内容放在filters目录下,每个目录下,有相应的py文件,文件中有相应的类。

此时通过@staticmethod装饰器,就可以让方法在调用时很清晰,让其他人可以一眼看出方法来自于哪里,比如下面这样写。

AdminFilter.filter_session(Utils.get_session())
AdminModule.get_user(user_id)

很清晰的知道,filter_session()在AdminFilter类下,用于判断session合法性,过滤非法用户。

对比一下Java,所有类中的方法都弄成静态方法的方式就是模仿Java项目开发的形式,可以很简单直观的明白方法的来源。

一个大型项目,所有类中的方法都弄成静态方法可能是一个不错的选择。

强制指定参数类型

Python中的方法不需要指定变量名,在代码量很多时,开发某个需求可能需要将参数一层层传递下去,此时方法参数类型不明确就比较尴尬,传参时,还要理解旧的逻辑是怎么使用这些参数的,从而大致判断参数的类型,如果方法本身就写的很庞大,那开发效率就会比较低了。

插句题外话,方法逻辑的长度最好要控制,别将所有的逻辑都写在一个方法上,最好将其分层,放到不同的方法中,方便阅读和单元测试。

回到刚刚的话,Python中方法参数没有类型会遇到上述问题,如果像Java一样就好了。

用类型标注?确实是个不错的方法,如下例子。

def myfun(id: int, params: dict) -> dict:
    res = AdminModule.get(id, params)
    return res

类型标注并不强制要求传相应类型的值,比如id标注要传int类型的值,但直接传入str类型的值也可以,如果逻辑没问题就不会抛出异常,这里通过AdminModule.get()方法通过id去获取相应的值,id为str其实也没影响,但我们想要一种强制方式,方法参数类型传错了,直接抛出异常,从而严格统一整个项目的代码风格。

弄个装饰器就好了。

import functools

class ParamTypeError(Exception):
    pass

def clear_param(**params):
    def decorate(func):
        @functools.wraps(func)
        def wrapper(**kwargs):
            for name, value in kwargs.items():
                if not isinstance(value, params[name]):
                    raise ParamTypeError(
                        'the {func_name} params type error.'.
                        format(func_name=func.__name__))
            result = func(**kwargs)
            return result
        return wrapper
    return decorate

clear_param是一个典型的带参数装饰器,该装饰器利用isinstance()方法对传入参数类型进行判断,如果类型不符,则直接抛出ParamTypeError。

使用如下。

@clear_param(a=int, b=int)  
def myfun(a, b):
    return a + b

res = myfun(a=1, b=2)
print(res)

整个项目通过这个装饰器实现方法参数类型的强制约束,这会让开发者开发时麻烦一点,但非常利于后期的维护与扩展,代码很清晰。

为复杂计算方法加缓存装饰器

缓存装饰器这件事情其实很常见,简单点的就是利用一个dict,以方法名与参数作为dict的唯一key,将方法计算的结果作为value,当该方法再次收到同样的参数时,直接将value返回则可。

上述方式太简单,没有涉及数据超时以及优先级的概念,比较好的方式是实现一个LRU(最近最少使用)队列来做,设置缓存空间大小,避免使用过多内存,此外,定时将不常用的缓存清除,这里有很多细节可以聊,在「懒编程」后面的内容中再详聊吧,如果你现在兴趣浓厚,可以看一下cachetoolscacheout这个两个Python实现的缓存模块,后面有机会,我会扒一扒其中一个的源码。

结尾

文中提出的这些装饰器用法只有两个目的,让Python大型项目更规范,人为的约束开发者随意释放自己的才华,此外就是加速复杂的计算方法,让项目运行的更快一些。

如果本文对你有所帮助与启发,点击「在看」支持二两。

最后,周围牛人真多,还要多跟大家探讨与学习。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值