仅在有显著优势时, 审慎地使用装饰器. 避免使用 staticmethod
. 减少使用 classmethod
.
定义:
装饰器(也就是@标记)作用在函数和方法上. 常见的装饰器是 @property
, 用于把方法转化为动态求值的属性. 不过, 也可以用装饰器语法自行定义装饰器. 具体地说, 若有一个函数 my_decorator
, 下面两段代码是等效的:
class C(object):
@my_decorator
def method(self):
# 函数体 ...
class C(object):
def method(self):
# 函数体 ...
method = my_decorator(method)
优点:
优雅地实现函数的变换; 这种变换可用于减少重复的代码, 或帮助检查不变式 (invariant).
缺点:
装饰器可以在函数的参数和返回值上执行任何操作, 这可能产生意外且隐蔽的效果. 而且, 装饰是在定义对象时执行. 模块级对象(类、模块级函数)的装饰器在导入模块时执行. 当装饰器代码出错时, 很难恢复正常控制流.
结论:
仅在有显著优势时, 审慎地使用装饰器. 装饰器的导入和命名规则与函数相同. 装饰器的pydoc注释应清楚地说明该函数是装饰器. 请为装饰器编写单元测试.
避免装饰器自身对外界的依赖(即不要依赖于文件, 套接字, 数据库连接等), 因为执行装饰器时(即导入模块时. pydoc
和其他工具也会导入你的模块) 可能无法连接到这些环境. 只要装饰器的调用参数正确, 装饰器应该 (尽最大努力) 保证运行成功.
装饰器是一种特殊形式的”顶级代码”. 参见关于《Python风格规范》中“主程序”的章节.
不得使用 staticmethod
, 除非为了兼容老代码库的 API 不得已而为之. 应该把静态方法改写为模块级函数.
仅在以下情况可以使用 classmethod
: 实现具名构造函数(named constructor); 在类方法中修改必要的全局状态 (例如进程内共享的缓存等)。