2016-08-30 11 views
2

doctestのドキュメントにはa section about execution contextがあります。 私の読んだことは、モジュール内のグローバルは、各docstringのテスト用にシャローコピーされているが、docstring内のテスト間ではリセットされないということです。doctestでのグローバル変数の変更

その説明に基づいて、私は次のdoctestを渡すだろうと思っているだろう:

X = 1 


def f(): 
    """Function F. 

    >>> X 
    1 
    >>> f() 
    2 
    >>> X 
    2 
    """ 
    global X 
    X = 2 
    return X 


def g(): 
    """Function G. 

    >>> g() 
    1 
    >>> X 
    1 
    """ 
    return X 

をしかし、その代わりに以下の試験を合格!

X = 1 


def f(): 
    """Function F. 

    >>> X 
    1 
    >>> f() 
    2 
    >>> X 
    1 
    """ 
    global X 
    X = 2 
    return X 


def g(): 
    """Function G. 

    >>> g() 
    2 
    >>> X 
    1 
    """ 
    return X 

グローバルがドキュメント間のテストで共有されているようですが、 しかし、関数呼び出し内でのみですか?

なぜこのような動作になりますか? これは、実行コンテキストとは別のグローバル辞書を持つ関数と関係がありますか?

答えて

0

正確ではありません。グローバルが浅くコピーされているのは間違いありませんが、実際に見ているのはグローバルのスコープ(キーワードglobalを使用しています)とPythonのモジュールレベルでの実際の動作です。代入(X = 2)の直後にpdb.set_trace()ファンクションfの中に入れてこれを確認することができます。

$ python -m doctest foo.py 
> /tmp/foo.py(18)f() 
-> return X 
(Pdb) bt 
    /usr/lib/python2.7/runpy.py(162)_run_module_as_main() 
-> "__main__", fname, loader, pkg_name) 
    /usr/lib/python2.7/runpy.py(72)_run_code() 
-> exec code in run_globals 
    /usr/lib/python2.7/doctest.py(2817)<module>() 
-> sys.exit(_test()) 
    /usr/lib/python2.7/doctest.py(2808)_test() 
-> failures, _ = testmod(m) 
    /usr/lib/python2.7/doctest.py(1911)testmod() 
-> runner.run(test) 
    /usr/lib/python2.7/doctest.py(1454)run() 
-> return self.__run(test, compileflags, out) 
    /usr/lib/python2.7/doctest.py(1315)__run() 
-> compileflags, 1) in test.globs 
    <doctest foo.f[1]>(1)<module>() 
-> f() 
> /tmp/foo.py(18)f() 
-> return X 
(Pdb) pp X 
2 

はい、値が実際に2fの範囲内ですが、のは、そのグローバルのを見てみましょう。現在のフレームとフレームの比較方法を見てみましょう。

(Pdb) id(globals()) 
140653053803048 # remember this number, and we go up a frame 
(Pdb) u 
> <doctest foo.f[1]>(1)<module>() 
-> f() 
(Pdb) id(globals()) 
140653053878632 # the "shallow" clone 
(Pdb) X 
1 
(Pdb) c 

ヘクタールああ、あなたは彼らが実際には同じものではないことを見ることができ、そしてグローバルがこのような理由のためのdoctestによって作成<doctest doc.f>モジュール内があるのでXは、確かに1であり、変更されていないこと。続けましょう。

(Pdb) id(globals()) 
140653053803048 # hey look, is the SAME number we remember 
(Pdb) u 
> <doctest foo.g[0]>(1)<module>() 
-> g() 
(Pdb) id(globals()) 
140653053872960 # note how this is a different shallow clone 

それでは、あなたが実際に見たことXが本当にfによってここにモジュールに変更したので、(それゆえg2を返しますdoctestの内のグローバルがあなたの元に一つとして同じものはないということですが、 Doctestモジュールの浅いコピースコープには含まれていません)、元々はモジュールからコピーされましたが、その変更は基礎となるモジュールに反映されませんでした。これはglobalキーワードがモジュールレベルではなくモジュールで動作するからです。

関連する問題