函数和类的类型和主题检查。

strict的Python项目详细描述


strict是一个模块,它解决了类型签入的常见需要 Python。

快速示例

功能约束

向函数签名添加类型约束:

from __future__ import print_function
from strict.functions import *

@expects(arg(float), arg(float), message=arg(str))
def multiply_and_print(a, b, message="You've got {result}"):
    print(message.format(result=(a * b)))

# This works just fine
multiply_and_print(2.0, 3.0)

# This raises a TypeConstraintError
multiply_and_print(int(2.0), 3.0)

向方法添加类型约束:

from __future__ import print_function
from strict.functions import *

class Foo(object):

    @expects(self, arg(str))
    def __init__(self, name):
        self.name = name

    def say_hello(self):
        print(", ".join(["Hello", self.name]))

# This works
f = Foo("Jim")
f.say_hello()

# This doesn't
f = Foo(123)
f.say_hello()

对函数的返回值添加约束:

from strict.functions import *

@returns(int)
def return_two():
    return 2

@returns(int)
def return_half():
    return 0.5

# This works fine
return_two()

# This raises an exception
return_half()

向函数添加主题约束和类型约束:

@expects(arg(float), arg(float, lambda x: x != 0))
def divide(a, b):
    "We need to make sure, that b isn't zero..."
    return a / b

# This works
divide(4.0, 2.0)

# This all fails with a TypeConstraintError
divide(4, 2.0)
divide(4.0, "poop")

# This fails with a SubjectConstraintError
divide(4.0, 0.0)

结构

定义结构:

from strict.structures import *

class Point(Structure):
    """
    Let's have a point, that can fit only on a certain area.
    """
    x = Field(float, lambda x: 0.0 < x < 1000.0)
    y = Field(float, lambda y: 0.0 < y < 1000.0)

    def __init__(self, x, y):
        self.x = x
        self.y = y

# This works
a = Point(10.0, 15.0)

# This all fails with the correct exception
Point(10, 15)
Point(10.0, 1001.0)
Point(-2.0, 50.0)

序列化结构:

from strict.structures import *

class Point(Structure):
    """
    Let's have a point, that can fit only on a certain area.
    """
    x = Field(float, lambda x: 0.0 < x < 1000.0)
    y = Field(float, lambda y: 0.0 < y < 1000.0)

    def __init__(self, x, y):
        self.x = x
        self.y = y

a = Point(10.0, 15.0)

# This outputs a dictionary
a.to_dict()

# This outputs a list
a.to_list()

我为什么要打支票?

尽管如此,在python中处理类型兼容性问题的常用习惯用法是 鸭子打字,在某些情况下是不够的。

关于usage context的信息通常隐式编码在 类名,duck类型通常无法处理,除非 引入迥然不同的类接口,或者仅仅引入kludge

考虑一下财务应用程序的以下类树:

                    +--------------------------+
                    |                          |
                    |   BaseVolatilitySurface  |
                    |                          |
                    +-------------+------------+
                                  |
                                  |
                                  |
                                  |
+---------------------------+     |     +-------------------------+
|                           |     |     |                         |
|  EquityVolatilitySurface  <-----+----->  RateVolatilitySurface  |
|                           |           |                         |
+---------------------------+           +-------------------------+

某些价值(通常是资产价格)的波动性是 金融衍生品的估值模型。在这种情况下,我们尝试在 运用市场隐含的股票和利率的波动性 价格。

这两个类基本上都有相同的接口如果我们依靠鸭子打字 意外地传递一个RateVolatilitySurface值一个股票期权,否 将引发异常,因为在技术上输入将满足 通过duck类型表示的约束。但是,结果是错误的 我们会得到一个典型的sh t-in,sht-out程序的例子。

显而易见的解决方案是在代码中添加大量 isinstance支票然而,这会很快导致您的业务代码 以样板检查和错误处理为主。为了避免这种情况,我试着 模块中最有用和最简单的模式:

  • 为函数参数和返回值分配约束
  • 创建一个对其属性进行严格类型检查的类 已填充__slots__变量。

2014年,杰夫金塔拉索夫(jevgeni@tarasov.ch

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
Eclipse程序参数不工作(java)?   java Eclipse RCP CommonNavigator工具提示?   调用实体管理器时的java空指针   安卓 java。lang.NoSuchMethodError:com。收拾一下。好的。内部的内部的调用NegatConnection   java Android:Sqlite DB升级openOrCreateDatabase   java@SpringBootTest和@Sql:脚本执行和上下文初始化的顺序   在Java中如何将HashMap转换为列表?   java组织。阿帕奇。火花sql。排到波乔   JavaSpring通用(参数化类型)转换服务?   java非法参数名Arquillian和Cucumber   java如何指定用于身份验证的方法?   java如何处理语法错误?   json实现补丁操作播放Java   java如何禁止不包含某些问题的提交   使用NIO的java(反)压缩文件   java模板方法需要在子构造函数中声明一个对象   java如何获取两个EditText字段的值并执行简单的数学运算   java无法从云数据流转换连接到云sql