1

願わくば、これがシリーズの最後の質問になることを願っています (要件が変わらない限り、私のプロジェクトはもうすぐ終わります)。

私はPyContract ( PyContractsではありません) を使用して、クラス メソッドのいくつかの制約を作成する作業を行っています。私の関数の 1 つに、不変式があります。ただし、この事後条件を構成するすべての変数が関数への入力パラメーターであるとは限りません。一部は、関数自体のスコープにローカルな変数です (ループ カウンターなど)。契約の事後条件句でそれらをキャプチャするにはどうすればよいですか?

これは、私が取り組んできたコードの 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. コントラクトでに変更arg5kwargs['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]:

さらに、不変チェックのコードがまったく実行されていないように見えるのは興味深いことです。

4

1 に答える 1

0

事後条件は、関数の実行が完了した後に実行されます。つまり、関数のローカル ( や など) を含むスタック フレームarg5gスコープ外になります。

ただし、これは契約を実装するライブラリにとってそれほど驚くべきことではありません。重要なのは、関数が実装することになっているインターフェイスで制約を宣言することですが、戻り値。

次の 2 つの方法で前進できます。

  1. コントラクトで確認したい状態を返す関数を作成します。ただし、内部状態が関数のインターフェイスの一部ではない場合、これは適切ではない可能性があります。

  2. PyContracts 以外のものを使用して、assertステートメント、またはおそらくraise AssertionError("while loop should have returned early")ループ後のステートメントなどの制約を適用します。

于 2012-10-24T06:54:29.367 に答える