【问题标题】:PyContract PostCondition Involving non-input-parameter VariablePyContract PostCondition 涉及非输入参数变量
【发布时间】:2012-10-24 04:26:39
【问题描述】:

希望这将是我在本系列中的最后一个问题(我的项目快结束了,除非需求发生变化)。

我正在使用PyContract(不是PyContracts)为类方法编写一些约束。在我的一个函数中,我有一个不变量。但是,并非构成此后置条件的所有变量都是函数的输入参数;有些是函数本身范围内的局部变量(循环计数器等)。我如何/可以在合同的后置条件条款中捕获它们?

这是我一直在使用的 MWE 代码:

def foo(*args, **kwargs):
    """
        pre:
            # some preconditions
        inv:
            # something that's clearly false
            1 == 2
        post:
            g < arg5
    """

    arg1 = kwargs['arg1']
    arg2 = kwargs['arg2']
    arg3 = kwargs['arg3']
    arg4 = kwargs['arg4']
    arg5 = kwargs['arg5']

    g = 0
    while g < arg5:
        vars = generate_data(arg1)
        best = max(arg2(var)for var in vars)
        if best >= arg3:
            return best
        # do stuff
        g += 1

当 PyContract 告诉我它不知道名称 garg5 时,问题就出现了。我把合约里的arg5改成了kwargs['arg5'],但是PyContract还是不知道g是什么。我如何/可以解决这个问题?

我得到的错误是:

Traceback (most recent call last):
  File "/Users/ashwin/github/local/Genetic-Framework/Genetic-Framework/Genetic/GA.py", line 245, in <module>
    answer = runTSPGA(*settings, **settings)
  File "<string>", line 3, in __assert_runTSPGA_chk
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/contract.py", line 1135, in call_public_function_all
    return _call_one_all(func, va, ka)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/contract.py", line 1321, in _call_one_all
    func.__assert_post(old, result, *va, **ka)
  File "<string>", line 4, in __assert_runTSPGA_post
NameError: global name 'g' is not defined

在后置条件声明中添加g 也无济于事:

post[kwargs, g]:

此外,有趣的是,用于不变检查的代码似乎根本没有运行

【问题讨论】:

  • 您能否将逐字错误消息添加到您的问题中?它有助于上下文。
  • kwagrs['agr#'] 不应该是kwargs['arg#'] 吗?
  • @AdamEberlin:是的。这是一个愚蠢的错字
  • @AdamEberlin:我已经改变了问题,以便更忠实于实际发生的事情。我第一次看错了一些错误
  • @Michael,您的编辑是originally rejected,但被重新提交并eventually approved。很好的收获。

标签: python design-by-contract invariants


【解决方案1】:

后置条件在函数完成运行后运行,这意味着包含函数局部变量(例如arg5g)的堆栈帧不再在作用域内。

这对于一个实现契约的库来说并不奇怪:重点是在函数应该实现的接口上声明约束,而您似乎想检查未创建的函数的内部状态在返回值中可见。

您可以前进的两种方式是:

  1. 使函数返回您想通过合约检查的状态。如果内部状态不是函数接口的一部分,这可能不合适。

  2. 使用 PyContracts 以外的东西来强制执行您的约束,例如 assert 语句,或者可能是循环后的 raise AssertionError("while loop should have returned early") 语句。

【讨论】:

  • 不变量正在运行。我用明显错误的不变量1==2 的例子证明了这一点。如果你在谈论后置条件,你说的很有道理
  • 你的问题是关于后置条件的,所以这就是我在回答中的内容。至于关于不变量的附录,PyContract 文档仅提到不变量 w.r.t。模块和类。您确定函数应该支持语法吗?如果是的话,你希望它提供什么前置条件和后置条件没有?
  • 我明白你的意思。我想检查不变量,即特定于正在运行的遗传算法的变量。我想我必须将它包装到一个类中才能使不变量正常工作
  • 如果您试图确保函数在运行时的某些点的内部状态是一致的,那么断言语句可能就是您想要的。
  • 我想到了断言语句。他们会工作的。另一个想法是将函数的那部分导出到另一个函数中(并在该函数上使用前置/后置条件)。第三个想法是将函数包装到一个类中。这第三种选择似乎对我 ATM 最有吸引力。
猜你喜欢
  • 2019-05-29
  • 2021-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-02
  • 2020-04-14
  • 2017-05-05
  • 1970-01-01
相关资源
最近更新 更多