PyContracts 是一个 Python 包,允许在函数参数和返回值上声明约束。约束可以使用 Python3 注解、装饰器或文档字符串中的 :type: 和 :rtype: 标签来指定。PyContracts 支持基本类型系统、变量绑定、算术约束,并提供了一些专用合约(特别是针对 Numpy 数组),以及扩展 API。
项目描述
PyContracts 是一个 Python 包,允许在函数参数和返回值上声明约束。它支持基本类型系统、变量绑定、算术约束,并提供了一些专用合约(特别是针对 Numpy 数组)。
作为一个快速介绍,请参阅 关于 PyContracts 的这个演示。
以下是一个简要概述。请参阅完整文档:<http://andreacensi.github.com/contracts/>
原因:PyContracts的目的不是将Python变成静态类型语言(尽管你可以尽可能严格),而是为了避免检查各种前置条件的耗时和混淆。事实上,除了类型约束外,我发现对值和大小约束的强制能力更有用。例如,“我需要一个至少包含3个正数的列表”可以表示为list[>=3](number, >0))。如果你觉得PyContracts对你来说过于复杂,你可能想尝试更简单的替代方案,如typecheck。如果你觉得PyContracts不够用,你可能想使用Haskell而不是Python。
指定契约:契约可以通过三种方式指定
使用``@contract``装饰器:
@contract(a='int,>0', b='list[N],N>0', returns='list[N]') def my_function(a, b): ...
使用注解(适用于Python 3)
@contract def my_function(a : 'int,>0', b : 'list[N],N>0') -> 'list[N]': # Requires b to be a nonempty list, and the return # value to have the same length. ...
使用文档字符串,带有:type:和:rtype:标签
@contract def my_function(a, b): """ Function description. :type a: int,>0 :type b: list[N],N>0 :rtype: list[N] """ ...
部署:在生产环境中,可以使用函数contracts.disable_all()禁用所有检查,因此性能损失为0。
扩展:你可以使用新的契约类型扩展PyContracts
new_contract('valid_name', lambda s: isinstance(s, str) and len(s)>0) @contract(names='dict(int: (valid_name, int))') def process_accounting(records): ...
任何Python类型都是契约
@contract(a=int, # simple contract b='int,>0' # more complicated ) def f(a, b): ...
强制接口:ContractsMeta是一个元类,就像ABCMeta一样,它将契约传播到子类
from contracts import contract, ContractsMeta, with_metaclass class Base(with_metaclass(ContractsMeta, object)): @abstractmethod @contract(probability='float,>=0,<=1') def sample(self, probability): pass class Derived(Base): # The contract above is automatically enforced, # without this class having to know about PyContracts at all! def sample(self, probability): ....
Numpy:有特殊的Numpy支持
@contract(image='array[HxWx3](uint8),H>10,W>10') def recolor(image): ...
状态:语法是稳定的,不会更改。PyContracts在Python 2.x上经过了非常充分的测试。
Python 3.x上的状态:我们已经达到了功能一致性!现在一切都在Python 3上工作。
贡献者:
Chris Beaumont(哈佛-史密森天体物理中心):$var语法;kwargs/args用于扩展。
Brett Graham(哈佛大学Rowland研究所):attr(name:type)语法用于检查属性的类型。
William Furr:错误报告和性能改进
Karol Kuczmarski(谷歌苏黎世):实现“字符串”和“unicode”契约
Maarten Derickx(莱顿大学):文档修正
Calen Pennington(edX):在check()函数内部禁用检查
Adam Palay(edX):实现环境变量启用/禁用覆盖
Ryan Heimbuch:错误报告
Bernhard Biskup:错误报告
asharp:错误修复
Dennis Kempin(谷歌总部):Sphinx风格的约束规范
Andy Hayden:Python 3支持,更高效的Numpy检查
Jonathan Sharpe:文件对象契约,而非操作符
(如果遗漏了任何人,请告诉我。)